pax_global_header 0000666 0000000 0000000 00000000064 12210155146 0014507 g ustar 00root root 0000000 0000000 52 comment=d779a39725fbaed377b037bb392c362eccac11e3
nagios/ 0000775 0000000 0000000 00000000000 12210155146 0012333 5 ustar 00root root 0000000 0000000 nagios/.gitignore 0000664 0000000 0000000 00000000246 12210155146 0014325 0 ustar 00root root 0000000 0000000 pkg
subst
pkginfo
Prototype
nagios.SPARC.pkg.tar.gz
autom4te.cache
config.log
config.status
daemon-init
Makefile
.deps/
.libs/
*.o
*.la
*.lo
*.gcda
*.gcno
/gmon.out
nagios/Changelog 0000664 0000000 0000000 00000123604 12210155146 0014153 0 ustar 00root root 0000000 0000000 #####################
Nagios 3.x Change Log
#####################
3.5.1 - 08/30/2013
------------------
* 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)
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
------------------
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)
3.4.1 - 05/11/2012
------------------
FIXES
* Double quotes in check_command definition break functionality (#332, reverts #86)
3.4.0 - 05/04/2012
------------------
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)
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
3.3.1 - 07/25/2011
------------------
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)
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)
WARNINGS
3.2.3 - 10/03/2010
------------------
ENHANCEMENTS
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)
WARNINGS
3.2.2 - 09/01/2010
------------------
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)
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)
3.2.1 - 03/09/2010
------------------
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)
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
3.2.0 - 08/12/2009
------------------
* 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
3.1.2 - 06/23/2009
------------------
* Fix for CPU hogging in service and host check scheduling logic
3.1.1 - 06/22/2009
------------------
* 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
3.1.0 - 01/25/2009
------------------
* 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
nagios/INSTALLING 0000664 0000000 0000000 00000000646 12210155146 0013730 0 ustar 00root root 0000000 0000000 Nagios Installation Instructions
--------------------------------
A quickstart installation guide can now be found in the HTML
documentation. You can find the quickstart guide (quickstart.html)
in the following subdirectory:
html/docs/
The quickstart covers all the basic steps you need to follow
to install Nagios, the Nagios plugins, and start out monitoring
the machine that Nagios is installed on.
Good luck!
nagios/LEGAL 0000664 0000000 0000000 00000001007 12210155146 0013100 0 ustar 00root root 0000000 0000000
All source code, binaries, documentation, information, and other files
contained in this distribution are provided AS IS with NO WARRANTY OF
ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS
FOR A PARTICULAR PURPOSE.
Nagios and the Nagios logo are trademarks, servicemarks, registered
trademarks or registered servicemarks owned by Nagios Enterprises, LLC.
All other trademarks, servicemarks, registered trademarks, and
registered servicemarks are the property of their respective owner(s).
nagios/LICENSE 0000664 0000000 0000000 00000043122 12210155146 0013342 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C) 19yy
This program 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
(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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
nagios/Makefile.in 0000664 0000000 0000000 00000030304 12210155146 0014400 0 ustar 00root root 0000000 0000000 ###############################
# Makefile for Nagios
#
# Last Modified: 04-13-2008
###############################
# Source code directories
SRC_BASE=@srcdir@/base
SRC_CGI=@srcdir@/cgi
SRC_HTM=@srcdir@/html
SRC_MODULE=@srcdir@/module
SRC_INCLUDE=@srcdir@/include
SRC_COMMON=@srcdir@/common
SRC_XDATA=@srcdir@/xdata
SRC_CONTRIB=@srcdir@/contrib
SRC_TTAP=@srcdir@/t-tap
CC=@CC@
CFLAGS=@CFLAGS@ @DEFS@
LDFLAGS=@LDFLAGS@ @LIBS@
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CHECKRESULTDIR=@CHECKRESULTDIR@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
CGIDIR=@sbindir@
LIBEXECDIR=@libexecdir@
HTMLDIR=@datadir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
COMMAND_OPTS=@COMMAND_OPTS@
HTTPD_CONF=@HTTPD_CONF@
INIT_DIR=@init_dir@
INIT_OPTS=-o root -g root
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 " clean"
@echo " install install-base install-cgis install-html install-exfoliation install-config install-init install-commandmode fullinstall"
# @echo " uninstall"
# FreeBSD make does not support -C option, so we'll use the Apache style... (patch by Stanley Hopcroft 12/27/1999)
pretty: indent
indent:
@sh indent-all.sh
ctags:
ctags -R
all:
cd $(SRC_BASE) && $(MAKE)
cd $(SRC_CGI) && $(MAKE)
cd $(SRC_HTM) && $(MAKE)
if [ x$(USE_EVENTBROKER) = xyes ]; then \
cd $(SRC_MODULE) && $(MAKE); \
fi
@echo ""
@echo "*** Compile finished ***"
@echo ""
@echo "If the main program and CGIs compiled without any errors, you"
@echo "can continue with installing Nagios as follows (type 'make'"
@echo "without any arguments for a list of all possible options):"
@echo ""
@echo " make install"
@echo " - This installs the main program, CGIs, and HTML files"
@echo ""
@echo " make install-init"
@echo " - This installs the init script in $(DESTDIR)$(INIT_DIR)"
@echo ""
@echo " make install-commandmode"
@echo " - This installs and configures permissions on the"
@echo " directory for holding the external command file"
@echo ""
@echo " make install-config"
@echo " - This installs *SAMPLE* config files in $(DESTDIR)$(CFGDIR)"
@echo " You'll have to modify these sample files before you can"
@echo " use Nagios. Read the HTML documentation for more info"
@echo " on doing this. Pay particular attention to the docs on"
@echo " object configuration files, as they determine what/how"
@echo " things get monitored!"
@echo ""
@echo " make install-webconf"
@echo " - This installs the Apache config file for the Nagios"
@echo " web interface"
@echo ""
@echo " make install-exfoliation"
@echo " - This installs the Exfoliation theme for the Nagios"
@echo " web interface"
@echo ""
@echo " make install-classicui"
@echo " - This installs the classic theme for the Nagios"
@echo " web interface"
@echo ""
@echo ""
@echo "*** Support Notes *******************************************"
@echo ""
@echo "If you have questions about configuring or running Nagios,"
@echo "please make sure that you:"
@echo ""
@echo " - Look at the sample config files"
@echo " - Read the documentation on the Nagios Library at:"
@echo " http://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"
@echo "help others help you. This might include:"
@echo ""
@echo " - What version of Nagios you are using"
@echo " - What version of the plugins you are using"
@echo " - Relevant snippets from your config files"
@echo " - Relevant error messages from the Nagios log file"
@echo ""
@echo "For more information on obtaining support for Nagios, visit:"
@echo ""
@echo " http://support.nagios.com"
@echo ""
@echo "*************************************************************"
@echo ""
@echo "Enjoy."
@echo ""
nagios:
cd $(SRC_BASE) && $(MAKE)
config:
@echo "Sample config files are automatically generated once you run the"
@echo "configure script. You can install the sample config files on your"
@echo "system by using the 'make install-config' command."
cgis:
cd $(SRC_CGI) && $(MAKE)
html:
cd $(SRC_HTM) && $(MAKE)
contrib:
cd $(SRC_CONTRIB) && $(MAKE)
modules:
cd $(SRC_MODULE) && $(MAKE)
clean:
cd $(SRC_BASE) && $(MAKE) $@
cd $(SRC_CGI) && $(MAKE) $@
cd $(SRC_COMMON) && $(MAKE) $@
cd $(SRC_XDATA) && $(MAKE) $@
cd $(SRC_HTM) && $(MAKE) $@
cd $(SRC_INCLUDE) && $(MAKE) $@
cd $(SRC_CONTRIB) && $(MAKE) $@
cd $(SRC_MODULE) && $(MAKE) $@
cd $(SRC_TTAP) && $(MAKE) $@
rm -f *.cfg core
rm -f *~ *.*~ */*~ */*.*~ */*/*.*~
distclean: clean
cd $(SRC_BASE) && $(MAKE) $@
cd $(SRC_CGI) && $(MAKE) $@
cd $(SRC_COMMON) && $(MAKE) $@
cd $(SRC_XDATA) && $(MAKE) $@
cd $(SRC_HTM) && $(MAKE) $@
cd $(SRC_INCLUDE) && $(MAKE) $@
cd $(SRC_CONTRIB) && $(MAKE) $@
cd $(SRC_MODULE) && $(MAKE) $@
cd $(SRC_TTAP) && $(MAKE) $@
rm -f sample-config/*.cfg sample-config/*.conf sample-config/template-object/*.cfg
rm -f daemon-init pkginfo
rm -f Makefile subst
rm -f config.log config.status config.cache
rm -f tags
devclean: distclean
test:
$(MAKE) test-perl
$(MAKE) test-tap
test-tap: tap/src/tap.o nagios cgis
@if [ x$(USE_LIBTAP) = xyes ]; then \
cd $(SRC_TTAP) && $(MAKE) test; \
else \
echo "NOTE: You must run configure with --enable-libtap to run the C tap tests"; \
fi
tap/src/tap.o:
cd tap && $(MAKE)
test-perl: cgis
cd t && $(MAKE) test
install-html:
cd $(SRC_HTM) && $(MAKE) install
make install-exfoliation
install-base:
cd $(SRC_BASE) && $(MAKE) install
install-cgis:
cd $(SRC_CGI) && $(MAKE) install
install:
cd $(SRC_BASE) && $(MAKE) $@
cd $(SRC_CGI) && $(MAKE) $@
cd $(SRC_HTM) && $(MAKE) $@
$(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-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;
@echo ""
@echo "*** Main program, CGIs and HTML files installed ***"
@echo ""
@echo "You can continue with installing Nagios as follows (type 'make'"
@echo "without any arguments for a list of all possible options):"
@echo ""
@echo " make install-init"
@echo " - This installs the init script in $(DESTDIR)$(INIT_DIR)"
@echo ""
@echo " make install-commandmode"
@echo " - This installs and configures permissions on the"
@echo " directory for holding the external command file"
@echo ""
@echo " make install-config"
@echo " - This installs sample config files in $(DESTDIR)$(CFGDIR)"
@echo ""
install-config:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CFGDIR)
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CFGDIR)/objects
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/nagios.cfg $(DESTDIR)$(CFGDIR)/nagios.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/cgi.cfg $(DESTDIR)$(CFGDIR)/cgi.cfg
$(INSTALL) -b -m 660 $(INSTALL_OPTS) sample-config/resource.cfg $(DESTDIR)$(CFGDIR)/resource.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/templates.cfg $(DESTDIR)$(CFGDIR)/objects/templates.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/commands.cfg $(DESTDIR)$(CFGDIR)/objects/commands.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/contacts.cfg $(DESTDIR)$(CFGDIR)/objects/contacts.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/timeperiods.cfg $(DESTDIR)$(CFGDIR)/objects/timeperiods.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/localhost.cfg $(DESTDIR)$(CFGDIR)/objects/localhost.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/windows.cfg $(DESTDIR)$(CFGDIR)/objects/windows.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/printer.cfg $(DESTDIR)$(CFGDIR)/objects/printer.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/switch.cfg $(DESTDIR)$(CFGDIR)/objects/switch.cfg
@echo ""
@echo "*** Config files installed ***"
@echo ""
@echo "Remember, these are *SAMPLE* config files. You'll need to read"
@echo "the documentation for more information on how to actually define"
@echo "services, hosts, etc. to fit your particular needs."
@echo ""
install-webconf:
$(INSTALL) -m 644 sample-config/httpd.conf $(DESTDIR)$(HTTPD_CONF)/nagios.conf
@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
@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
@echo ""
@echo "*** Classic theme installed ***"
@echo "NOTE: Use 'make install-exfoliation' to use new Nagios theme";
@echo ""
install-init: install-daemoninit
install-daemoninit:
$(INSTALL) -m 755 -d $(INIT_OPTS) $(DESTDIR)$(INIT_DIR)
$(INSTALL) -m 755 $(INIT_OPTS) daemon-init $(DESTDIR)$(INIT_DIR)/nagios
@echo ""
@echo "*** Init script installed ***"
@echo ""
install-commandmode:
$(INSTALL) -m 775 $(COMMAND_OPTS) -d $(DESTDIR)$(LOGDIR)/rw
chmod g+s $(DESTDIR)$(LOGDIR)/rw
@echo ""
@echo "*** External command directory configured ***"
@echo ""
fullinstall: install install-init install-commandmode install-webconf
# Uninstall is too destructive if base install directory is /usr, etc.
#uninstall:
# rm -rf $(DESTDIR)$(BINDIR)/nagios $(DESTDIR)$(CGIDIR)/*.cgi $(DESTDIR)$(CFGDIR)/*.cfg $(DESTDIR)$(HTMLDIR)
#
# Targets for creating packages on various architectures
#
# Solaris pkgmk
PACKDIR=@PACKDIR@
VERSION=@VERSION@
Prototype:
if [ ! -d $(PACKDIR) ] ; then mkdir $(PACKDIR); fi
if [ ! -d $(PACKDIR)/etc ] ; then mkdir $(PACKDIR)/etc; fi
if [ ! -d $(PACKDIR)/etc/init.d ] ; then mkdir $(PACKDIR)/etc/init.d; fi
if [ ! -d $(PACKDIR)/etc/nagios ] ; then mkdir $(PACKDIR)/etc/nagios; fi
$(MAKE) all
$(MAKE) DESTDIR=$(PACKDIR) INIT_OPTS='' INSTALL_OPTS='' COMMAND_OPTS='' nagios_grp='' nagios_usr='' fullinstall
$(INSTALL) -m 644 sample-config/nagios.cfg $(PACKDIR)$(CFGDIR)/nagios.cfg.$(VERSION)
$(INSTALL) -m 644 sample-config/cgi.cfg $(PACKDIR)$(CFGDIR)/cgi.cfg.$(VERSION)
$(INSTALL) -m 640 sample-config/resource.cfg $(PACKDIR)$(CFGDIR)/resource.cfg.$(VERSION)
$(INSTALL) -m 664 sample-config/template-object/bigger.cfg $(PACKDIR)$(CFGDIR)/bigger.cfg.$(VERSION)
$(INSTALL) -m 664 sample-config/template-object/minimal.cfg $(PACKDIR)$(CFGDIR)/minimal.cfg.$(VERSION)
$(INSTALL) -m 664 sample-config/template-object/checkcommands.cfg $(PACKDIR)$(CFGDIR)/checkcommands.cfg.$(VERSION)
$(INSTALL) -m 664 sample-config/template-object/misccommands.cfg $(PACKDIR)$(CFGDIR)/misccommands.cfg.$(VERSION)
cd contrib; $(MAKE) all; $(MAKE) DESTDIR=$(PACKDIR) INIT_OPTS='' INSTALL_OPTS='' COMMAND_OPTS='' nagios_grp='' nagios_usr='' install
echo i pkginfo> Prototype
if [ -f checkinstall ] ; then echo i checkinstall>> Prototype; fi
if [ -f preinstall ] ; then echo i preinstall>> Prototype; fi
if [ -f postinstall ] ; then echo i postinstall>> Prototype; fi
pkgproto $(PACKDIR)=/ | sed -e "s|$(LOGNAME) $(GROUP)$$|root root|" | egrep -v "(s|d) none (/|/etc|/var|/usr|/usr/local) " >> Prototype
pkg/nagios/pkgmap: Prototype
mkdir $(PACKDIR)/nagios
pkgmk -o -r / -f Prototype -d $(PACKDIR) nagios
nagios.SPARC.pkg.tar.gz: pkg/nagios/pkgmap
cd $(PACKDIR) && tar -cf - nagios | gzip -9 -c > ../nagios.SPARC.pkg.tar.gz
pkgset: nagios.SPARC.pkg.tar.gz
pkgclean:
rm -rf pkg Prototype nagios.SPARC.pkg.tar.gz
# Targets that always get built
.PHONY: indent clean clean distclean
nagios/OutputTrap.pm 0000664 0000000 0000000 00000001351 12210155146 0015020 0 ustar 00root root 0000000 0000000 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__
nagios/README 0000664 0000000 0000000 00000002003 12210155146 0013206 0 ustar 00root root 0000000 0000000 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)
nagios/THANKS 0000664 0000000 0000000 00000011653 12210155146 0013254 0 ustar 00root root 0000000 0000000 =======
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.
* 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
* 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
* 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
nagios/UPGRADING 0000664 0000000 0000000 00000000513 12210155146 0013575 0 ustar 00root root 0000000 0000000 Upgrading to Nagios 3.x
-----------------------
The HTML documentation covers what you need to know in order
to upgrade from Nagios 2.x You can find the documentation in
the following subdirectory:
html/docs
Make sure to read the following sections:
- "What's New" (whatsnew.html)
- "Upgrading Nagios" (upgrading.html)
nagios/base/ 0000775 0000000 0000000 00000000000 12210155146 0013245 5 ustar 00root root 0000000 0000000 nagios/base/.gitignore 0000664 0000000 0000000 00000000026 12210155146 0015233 0 ustar 00root root 0000000 0000000 *.o
nagios
nagiostats
nagios/base/Makefile.in 0000664 0000000 0000000 00000013633 12210155146 0015320 0 ustar 00root root 0000000 0000000 ############################
# Makefile for Nagios
#
# Last Modified: 12-05-2008
############################
# Source code directories
SRC_COMMON=../common
SRC_INCLUDE=../include
SRC_XDATA=../xdata
CC=@CC@
CFLAGS=-Wall @CFLAGS@ @DEFS@ -DNSCORE
# Compiler flags for use with gprof
#CFLAGS=-pg -DHAVE_CONFIG_H -DNSCORE
# Compiler flags for use with Valgrind
#CFLAGS=-O0 -g -DHAVE_CONFIG_H -DNSCORE
# Compiler flags for optimization (overrides default)
#CFLAGS=-O3 -Wall -fno-strict-aliasing -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -DHAVE_CONFIG_H -DNSCORE
# Compiler flags for optimization (complements default)
#CFLAGS_WARN=-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs
#CFLAGS_DEBUG=-ggdb3 -g3
#CFLAGS_GPROF=-pg
#CFLAGS+=$(CFLAGS_WARN) $(CFLAGS_DEBUG) $(CFLAGS_GPROF)
LDFLAGS=@LDFLAGS@
LIBS=@LIBS@
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
CGIDIR=@sbindir@
HTMLDIR=@datarootdir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
COMMAND_OPTS=@COMMAND_OPTS@
STRIP=@STRIP@
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
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)
OBJDEPS=$(ODATADEPS) $(ODATADEPS) $(RDATADEPS) $(CDATADEPS) $(SDATADEPS) $(PDATADEPS) $(DDATADEPS) $(BROKER_H)
all: nagios nagiostats
######## REQUIRED FILES ##########
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)
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)
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)
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)
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)
$(SRC_COMMON)/shared.o: $(SRC_COMMON)/shared.c
$(CC) $(CFLAGS) -c -o $@ $<
########## 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)
nagiostats: nagiostats.c $(SRC_INCLUDE)/locations.h
$(CC) $(CFLAGS) -o $@ nagiostats.c $(LDFLAGS) $(MATHLIBS) $(LIBS)
$(OBJS): $(SRC_INCLUDE)/locations.h
clean:
rm -f nagios nagiostats core *.o gmon.out
rm -f *~ *.*~
distclean: clean
rm -f perlxsi.c
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) @nagios_name@ $(DESTDIR)$(BINDIR)
$(INSTALL) -m 774 $(INSTALL_OPTS) @nagiostats_name@ $(DESTDIR)$(BINDIR)
strip-post-install:
$(STRIP) $(DESTDIR)$(BINDIR)/@nagios_name@
$(STRIP) $(DESTDIR)$(BINDIR)/@nagiostats_name@
nagios/base/broker.c 0000664 0000000 0000000 00000071156 12210155146 0014707 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* 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:
*
* 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/nagios.h"
#include "../include/broker.h"
#include "../include/nebcallbacks.h"
#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
/******************************************************************/
/************************* EVENT FUNCTIONS ************************/
/******************************************************************/
/* sends program data (starts, restarts, stops, etc.) to broker */
void broker_program_state(int type, int flags, int attr, struct timeval *timestamp) {
nebstruct_process_data ds;
if(!(event_broker_options & BROKER_PROGRAM_STATE))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_PROCESS_DATA, (void *)&ds);
return;
}
/* send timed event data to broker */
void broker_timed_event(int type, int flags, int attr, timed_event *event, struct timeval *timestamp) {
nebstruct_timed_event_data ds;
if(!(event_broker_options & BROKER_TIMED_EVENTS))
return;
if(event == NULL)
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.event_type = event->event_type;
ds.recurring = event->recurring;
ds.run_time = event->run_time;
ds.event_data = event->event_data;
ds.event_ptr = (void *)event;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_TIMED_EVENT_DATA, (void *)&ds);
return;
}
/* send log data to broker */
void broker_log_data(int type, int flags, int attr, char *data, unsigned long data_type, time_t entry_time, struct timeval *timestamp) {
nebstruct_log_data ds;
if(!(event_broker_options & BROKER_LOGGED_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.entry_time = entry_time;
ds.data_type = data_type;
ds.data = data;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_LOG_DATA, (void *)&ds);
return;
}
/* send system command data to broker */
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) {
nebstruct_system_command_data ds;
if(!(event_broker_options & BROKER_SYSTEM_COMMANDS))
return;
if(cmd == NULL)
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.start_time = start_time;
ds.end_time = end_time;
ds.timeout = timeout;
ds.command_line = cmd;
ds.early_timeout = early_timeout;
ds.execution_time = exectime;
ds.return_code = retcode;
ds.output = output;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_SYSTEM_COMMAND_DATA, (void *)&ds);
return;
}
/* send event handler data to broker */
int broker_event_handler(int type, int flags, int attr, int eventhandler_type, void *data, int state, int state_type, struct timeval start_time, struct timeval end_time, double exectime, int timeout, int early_timeout, int retcode, char *cmd, char *cmdline, char *output, struct timeval *timestamp) {
service *temp_service = NULL;
host *temp_host = NULL;
char *command_buf = NULL;
char *command_name = NULL;
char *command_args = NULL;
nebstruct_event_handler_data ds;
int return_code = OK;
if(!(event_broker_options & BROKER_EVENT_HANDLERS))
return return_code;
if(data == NULL)
return ERROR;
/* get command name/args */
if(cmd != NULL) {
command_buf = (char *)strdup(cmd);
command_name = strtok(command_buf, "!");
command_args = strtok(NULL, "\x0");
}
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.eventhandler_type = eventhandler_type;
if(eventhandler_type == SERVICE_EVENTHANDLER || eventhandler_type == GLOBAL_SERVICE_EVENTHANDLER) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
}
ds.object_ptr = data;
ds.state = state;
ds.state_type = state_type;
ds.start_time = start_time;
ds.end_time = end_time;
ds.timeout = timeout;
ds.command_name = command_name;
ds.command_args = command_args;
ds.command_line = cmdline;
ds.early_timeout = early_timeout;
ds.execution_time = exectime;
ds.return_code = retcode;
ds.output = output;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_EVENT_HANDLER_DATA, (void *)&ds);
/* free memory */
my_free(command_buf);
return return_code;
}
/* 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) {
char *command_buf = NULL;
char *command_name = NULL;
char *command_args = NULL;
nebstruct_host_check_data ds;
int return_code = OK;
if(!(event_broker_options & BROKER_HOST_CHECKS))
return OK;
if(hst == NULL)
return ERROR;
/* get command name/args */
if(cmd != NULL) {
command_buf = (char *)strdup(cmd);
command_name = strtok(command_buf, "!");
command_args = strtok(NULL, "\x0");
}
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.host_name = hst->name;
ds.object_ptr = (void *)hst;
ds.check_type = check_type;
ds.current_attempt = hst->current_attempt;
ds.max_attempts = hst->max_attempts;
ds.state = state;
ds.state_type = state_type;
ds.timeout = timeout;
ds.command_name = command_name;
ds.command_args = command_args;
ds.command_line = cmdline;
ds.start_time = start_time;
ds.end_time = end_time;
ds.early_timeout = early_timeout;
ds.execution_time = exectime;
ds.latency = latency;
ds.return_code = retcode;
ds.output = output;
ds.long_output = long_output;
ds.perf_data = perfdata;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_HOST_CHECK_DATA, (void *)&ds);
/* free data */
my_free(command_buf);
return return_code;
}
/* 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) {
char *command_buf = NULL;
char *command_name = NULL;
char *command_args = NULL;
nebstruct_service_check_data ds;
int return_code = OK;
if(!(event_broker_options & BROKER_SERVICE_CHECKS))
return OK;
if(svc == NULL)
return ERROR;
/* get command name/args */
if(cmd != NULL) {
command_buf = (char *)strdup(cmd);
command_name = strtok(command_buf, "!");
command_args = strtok(NULL, "\x0");
}
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.host_name = svc->host_name;
ds.service_description = svc->description;
ds.object_ptr = (void *)svc;
ds.check_type = check_type;
ds.current_attempt = svc->current_attempt;
ds.max_attempts = svc->max_attempts;
ds.state = svc->current_state;
ds.state_type = svc->state_type;
ds.timeout = timeout;
ds.command_name = command_name;
ds.command_args = command_args;
ds.command_line = cmdline;
ds.start_time = start_time;
ds.end_time = end_time;
ds.early_timeout = early_timeout;
ds.execution_time = exectime;
ds.latency = latency;
ds.return_code = retcode;
ds.output = svc->plugin_output;
ds.long_output = svc->long_plugin_output;
ds.perf_data = svc->perf_data;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_SERVICE_CHECK_DATA, (void *)&ds);
/* free data */
my_free(command_buf);
return return_code;
}
/* send comment data to broker */
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) {
nebstruct_comment_data ds;
if(!(event_broker_options & BROKER_COMMENT_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.comment_type = comment_type;
ds.entry_type = entry_type;
ds.host_name = host_name;
ds.service_description = svc_description;
ds.object_ptr = NULL; /* not implemented yet */
ds.entry_time = entry_time;
ds.author_name = author_name;
ds.comment_data = comment_data;
ds.persistent = persistent;
ds.source = source;
ds.expires = expires;
ds.expire_time = expire_time;
ds.comment_id = comment_id;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_COMMENT_DATA, (void *)&ds);
return;
}
/* send downtime data to broker */
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) {
nebstruct_downtime_data ds;
if(!(event_broker_options & BROKER_DOWNTIME_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.downtime_type = downtime_type;
ds.host_name = host_name;
ds.service_description = svc_description;
ds.object_ptr = NULL; /* not implemented yet */
ds.entry_time = entry_time;
ds.author_name = author_name;
ds.comment_data = comment_data;
ds.start_time = start_time;
ds.end_time = end_time;
ds.fixed = fixed;
ds.duration = duration;
ds.triggered_by = triggered_by;
ds.downtime_id = downtime_id;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_DOWNTIME_DATA, (void *)&ds);
return;
}
/* send flapping data to broker */
void broker_flapping_data(int type, int flags, int attr, int flapping_type, void *data, double percent_change, double high_threshold, double low_threshold, struct timeval *timestamp) {
nebstruct_flapping_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
if(!(event_broker_options & BROKER_FLAPPING_DATA))
return;
if(data == NULL)
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.flapping_type = flapping_type;
if(flapping_type == SERVICE_FLAPPING) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.comment_id = temp_service->flapping_comment_id;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.comment_id = temp_host->flapping_comment_id;
}
ds.object_ptr = data;
ds.percent_change = percent_change;
ds.high_threshold = high_threshold;
ds.low_threshold = low_threshold;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_FLAPPING_DATA, (void *)&ds);
return;
}
/* sends program status updates to broker */
void broker_program_status(int type, int flags, int attr, struct timeval *timestamp) {
nebstruct_program_status_data ds;
if(!(event_broker_options & BROKER_STATUS_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
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;
ds.passive_service_checks_enabled = accept_passive_service_checks;
ds.active_host_checks_enabled = execute_host_checks;
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;
ds.modified_host_attributes = modified_host_process_attributes;
ds.modified_service_attributes = modified_service_process_attributes;
ds.global_host_event_handler = global_host_event_handler;
ds.global_service_event_handler = global_service_event_handler;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_PROGRAM_STATUS_DATA, (void *)&ds);
return;
}
/* sends host status updates to broker */
void broker_host_status(int type, int flags, int attr, host *hst, struct timeval *timestamp) {
nebstruct_host_status_data ds;
if(!(event_broker_options & BROKER_STATUS_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.object_ptr = (void *)hst;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_HOST_STATUS_DATA, (void *)&ds);
return;
}
/* sends service status updates to broker */
void broker_service_status(int type, int flags, int attr, service *svc, struct timeval *timestamp) {
nebstruct_service_status_data ds;
if(!(event_broker_options & BROKER_STATUS_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.object_ptr = (void *)svc;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_SERVICE_STATUS_DATA, (void *)&ds);
return;
}
/* sends contact status updates to broker */
void broker_contact_status(int type, int flags, int attr, contact *cntct, struct timeval *timestamp) {
nebstruct_service_status_data ds;
if(!(event_broker_options & BROKER_STATUS_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.object_ptr = (void *)cntct;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_CONTACT_STATUS_DATA, (void *)&ds);
return;
}
/* send notification data to broker */
int broker_notification_data(int type, int flags, int attr, int notification_type, int reason_type, struct timeval start_time, struct timeval end_time, void *data, char *ack_author, char *ack_data, int escalated, int contacts_notified, struct timeval *timestamp) {
nebstruct_notification_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
int return_code = OK;
if(!(event_broker_options & BROKER_NOTIFICATIONS))
return return_code;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.notification_type = notification_type;
ds.start_time = start_time;
ds.end_time = end_time;
ds.reason_type = reason_type;
if(notification_type == SERVICE_NOTIFICATION) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.state = temp_service->current_state;
ds.output = temp_service->plugin_output;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.state = temp_host->current_state;
ds.output = temp_host->plugin_output;
}
ds.object_ptr = data;
ds.ack_author = ack_author;
ds.ack_data = ack_data;
ds.escalated = escalated;
ds.contacts_notified = contacts_notified;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_NOTIFICATION_DATA, (void *)&ds);
return return_code;
}
/* send contact notification data to broker */
int broker_contact_notification_data(int type, int flags, int attr, int notification_type, int reason_type, struct timeval start_time, struct timeval end_time, void *data, contact *cntct, char *ack_author, char *ack_data, int escalated, struct timeval *timestamp) {
nebstruct_contact_notification_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
int return_code = OK;
if(!(event_broker_options & BROKER_NOTIFICATIONS))
return return_code;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.notification_type = notification_type;
ds.start_time = start_time;
ds.end_time = end_time;
ds.reason_type = reason_type;
ds.contact_name = cntct->name;
if(notification_type == SERVICE_NOTIFICATION) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.state = temp_service->current_state;
ds.output = temp_service->plugin_output;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.state = temp_host->current_state;
ds.output = temp_host->plugin_output;
}
ds.object_ptr = data;
ds.contact_ptr = (void *)cntct;
ds.ack_author = ack_author;
ds.ack_data = ack_data;
ds.escalated = escalated;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_CONTACT_NOTIFICATION_DATA, (void *)&ds);
return return_code;
}
/* send contact notification data to broker */
int broker_contact_notification_method_data(int type, int flags, int attr, int notification_type, int reason_type, struct timeval start_time, struct timeval end_time, void *data, contact *cntct, char *cmd, char *ack_author, char *ack_data, int escalated, struct timeval *timestamp) {
nebstruct_contact_notification_method_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
char *command_buf = NULL;
char *command_name = NULL;
char *command_args = NULL;
int return_code = OK;
if(!(event_broker_options & BROKER_NOTIFICATIONS))
return return_code;
/* get command name/args */
if(cmd != NULL) {
command_buf = (char *)strdup(cmd);
command_name = strtok(command_buf, "!");
command_args = strtok(NULL, "\x0");
}
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.notification_type = notification_type;
ds.start_time = start_time;
ds.end_time = end_time;
ds.reason_type = reason_type;
ds.contact_name = cntct->name;
ds.command_name = command_name;
ds.command_args = command_args;
if(notification_type == SERVICE_NOTIFICATION) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.state = temp_service->current_state;
ds.output = temp_service->plugin_output;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.state = temp_host->current_state;
ds.output = temp_host->plugin_output;
}
ds.object_ptr = data;
ds.contact_ptr = (void *)cntct;
ds.ack_author = ack_author;
ds.ack_data = ack_data;
ds.escalated = escalated;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_CONTACT_NOTIFICATION_METHOD_DATA, (void *)&ds);
/* free memory */
my_free(command_buf);
return return_code;
}
/* sends adaptive programs updates to broker */
void broker_adaptive_program_data(int type, int flags, int attr, int command_type, unsigned long modhattr, unsigned long modhattrs, unsigned long modsattr, unsigned long modsattrs, struct timeval *timestamp) {
nebstruct_adaptive_program_data ds;
if(!(event_broker_options & BROKER_ADAPTIVE_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.command_type = command_type;
ds.modified_host_attribute = modhattr;
ds.modified_host_attributes = modhattrs;
ds.modified_service_attribute = modsattr;
ds.modified_service_attributes = modsattrs;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_ADAPTIVE_PROGRAM_DATA, (void *)&ds);
return;
}
/* sends adaptive host updates to broker */
void broker_adaptive_host_data(int type, int flags, int attr, host *hst, int command_type, unsigned long modattr, unsigned long modattrs, struct timeval *timestamp) {
nebstruct_adaptive_host_data ds;
if(!(event_broker_options & BROKER_ADAPTIVE_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.command_type = command_type;
ds.modified_attribute = modattr;
ds.modified_attributes = modattrs;
ds.object_ptr = (void *)hst;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_ADAPTIVE_HOST_DATA, (void *)&ds);
return;
}
/* sends adaptive service updates to broker */
void broker_adaptive_service_data(int type, int flags, int attr, service *svc, int command_type, unsigned long modattr, unsigned long modattrs, struct timeval *timestamp) {
nebstruct_adaptive_service_data ds;
if(!(event_broker_options & BROKER_ADAPTIVE_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.command_type = command_type;
ds.modified_attribute = modattr;
ds.modified_attributes = modattrs;
ds.object_ptr = (void *)svc;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_ADAPTIVE_SERVICE_DATA, (void *)&ds);
return;
}
/* sends adaptive contact updates to broker */
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) {
nebstruct_adaptive_contact_data ds;
if(!(event_broker_options & BROKER_ADAPTIVE_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.command_type = command_type;
ds.modified_attribute = modattr;
ds.modified_attributes = modattrs;
ds.modified_host_attribute = modhattr;
ds.modified_host_attributes = modhattrs;
ds.modified_service_attribute = modsattr;
ds.modified_service_attributes = modsattrs;
ds.object_ptr = (void *)cntct;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_ADAPTIVE_CONTACT_DATA, (void *)&ds);
return;
}
/* sends external commands to broker */
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) {
nebstruct_external_command_data ds;
if(!(event_broker_options & BROKER_EXTERNALCOMMAND_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.command_type = command_type;
ds.entry_time = entry_time;
ds.command_string = command_string;
ds.command_args = command_args;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_EXTERNAL_COMMAND_DATA, (void *)&ds);
return;
}
/* brokers aggregated status dumps */
void broker_aggregated_status_data(int type, int flags, int attr, struct timeval *timestamp) {
nebstruct_aggregated_status_data ds;
if(!(event_broker_options & BROKER_STATUS_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_AGGREGATED_STATUS_DATA, (void *)&ds);
return;
}
/* brokers retention data */
void broker_retention_data(int type, int flags, int attr, struct timeval *timestamp) {
nebstruct_retention_data ds;
if(!(event_broker_options & BROKER_RETENTION_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_RETENTION_DATA, (void *)&ds);
return;
}
/* send acknowledgement data to broker */
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) {
nebstruct_acknowledgement_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
if(!(event_broker_options & BROKER_ACKNOWLEDGEMENT_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.acknowledgement_type = acknowledgement_type;
if(acknowledgement_type == SERVICE_ACKNOWLEDGEMENT) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.state = temp_service->current_state;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.state = temp_host->current_state;
}
ds.object_ptr = data;
ds.author_name = ack_author;
ds.comment_data = ack_data;
ds.is_sticky = (subtype == ACKNOWLEDGEMENT_STICKY) ? TRUE : FALSE;
ds.notify_contacts = notify_contacts;
ds.persistent_comment = persistent_comment;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_ACKNOWLEDGEMENT_DATA, (void *)&ds);
return;
}
/* send state change data to broker */
void broker_statechange_data(int type, int flags, int attr, int statechange_type, void *data, int state, int state_type, int current_attempt, int max_attempts, struct timeval *timestamp) {
nebstruct_statechange_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
if(!(event_broker_options & BROKER_STATECHANGE_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.statechange_type = statechange_type;
if(statechange_type == SERVICE_STATECHANGE) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.output = temp_service->plugin_output;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.output = temp_host->plugin_output;
}
ds.object_ptr = data;
ds.state = state;
ds.state_type = state_type;
ds.current_attempt = current_attempt;
ds.max_attempts = max_attempts;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_STATE_CHANGE_DATA, (void *)&ds);
return;
}
/******************************************************************/
/************************ UTILITY FUNCTIONS ***********************/
/******************************************************************/
/* gets timestamp for use by broker */
struct timeval get_broker_timestamp(struct timeval *timestamp) {
struct timeval tv;
if(timestamp == NULL)
gettimeofday(&tv, NULL);
else
tv = *timestamp;
return tv;
}
#endif
nagios/base/checks.c 0000664 0000000 0000000 00000506253 12210155146 0014664 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* 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:
*
* 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/comments.h"
#include "../include/common.h"
#include "../include/statusdata.h"
#include "../include/downtime.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/broker.h"
#include "../include/perfdata.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;
}
}
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");
return OK;
}
/******************************************************************/
/****************** SERVICE MONITORING FUNCTIONS ******************/
/******************************************************************/
/* executes a scheduled service check */
int run_scheduled_service_check(service *svc, int check_options, double latency) {
int result = OK;
time_t current_time = 0L;
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
int time_is_valid = TRUE;
if(svc == NULL)
return ERROR;
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_scheduled_service_check() start\n");
log_debug_info(DEBUGL_CHECKS, 0, "Attempting to run scheduled check of service '%s' on host '%s': check options=%d, latency=%lf\n", svc->description, svc->host_name, check_options, latency);
/*
* reset the next_check_event so we know it's
* no longer in the scheduling queue
*/
svc->next_check_event = NULL;
/* attempt to run the check */
result = run_async_service_check(svc, check_options, latency, TRUE, TRUE, &time_is_valid, &preferred_time);
/* an error occurred, so reschedule the check */
if(result == ERROR) {
log_debug_info(DEBUGL_CHECKS, 1, "Unable to run scheduled service check at this time\n");
/* only attempt to (re)schedule checks that should get checked... */
if(svc->should_be_scheduled == TRUE) {
/* get current time */
time(¤t_time);
/* determine next time we should check the service if needed */
/* if service has no check interval, schedule it again for 5 minutes from now */
if(current_time >= preferred_time)
preferred_time = current_time + ((svc->check_interval <= 0) ? 300 : (svc->check_interval * interval_length));
/* make sure we rescheduled the next service check at a valid time */
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(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 = (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);
log_debug_info(DEBUGL_CHECKS, 1, "Unable to find any valid times to reschedule the next service check!\n");
}
/* this service could be rescheduled... */
else {
svc->next_check = next_valid_time;
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 */
if(svc->should_be_scheduled == TRUE)
schedule_service_check(svc, svc->next_check, check_options);
/* update the status log */
update_service_status(svc, FALSE);
return ERROR;
}
return OK;
}
/* forks a child process to run a service check, but does not wait for the service check result */
int run_async_service_check(service *svc, 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;
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;
#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");
/* make sure we have something */
if(svc == NULL)
return ERROR;
/* is the service check viable at this time? */
if(check_service_check_viability(svc, check_options, time_is_valid, preferred_time) == ERROR)
return ERROR;
/* find the host associated with this service */
if((temp_host = svc->host_ptr) == NULL)
return ERROR;
/******** GOOD TO GO FOR A REAL SERVICE CHECK AT THIS POINT ********/
#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_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 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)
*preferred_time += (svc->check_interval * interval_length);
return ERROR;
}
/* neb module wants to override (or cancel) the service check - perhaps it will check the service 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
log_debug_info(DEBUGL_CHECKS, 0, "Checking service '%s' on host '%s'...\n", svc->description, svc->host_name);
/* clear check options - we don't want old check options retained */
/* only clear check options for scheduled checks - ondemand checks shouldn't affected retained check options */
if(scheduled_check == TRUE)
svc->check_options = CHECK_OPTION_NONE;
/* update latency for macros, event broker, save old value for later */
old_latency = svc->latency;
svc->latency = latency;
/* grab the host and service macro variables */
memset(&mac, 0, sizeof(mac));
grab_host_macros_r(&mac, temp_host);
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);
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);
if(preferred_time)
*preferred_time += (svc->check_interval * interval_length);
svc->latency = old_latency;
return ERROR;
}
/* process any macros contained in the argument */
process_macros_r(&mac, raw_command, &processed_command, 0);
my_free(raw_command);
if(processed_command == NULL) {
clear_volatile_macros_r(&mac);
log_debug_info(DEBUGL_CHECKS, 0, "Processed check command for service '%s' on host '%s' was NULL - aborting.\n", svc->description, svc->host_name);
if(preferred_time)
*preferred_time += (svc->check_interval * interval_length);
svc->latency = old_latency;
return ERROR;
}
/* get the command start time */
gettimeofday(&start_time, NULL);
#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 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;
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;
}
/* handles asynchronous service check results */
int handle_async_service_check_result(service *temp_service, check_result *queued_check_result) {
host *temp_host = NULL;
time_t next_service_check = 0L;
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
int reschedule_check = FALSE;
int state_change = FALSE;
int hard_state_change = FALSE;
int first_host_check_initiated = FALSE;
int route_result = HOST_UP;
time_t current_time = 0L;
int state_was_logged = FALSE;
char *old_plugin_output = NULL;
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");
/* make sure we have what we need */
if(temp_service == NULL || queued_check_result == NULL)
return ERROR;
/* 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);
/* decrement the number of service checks still out there... */
if(queued_check_result->check_type == SERVICE_CHECK_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(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) {
log_debug_info(DEBUGL_CHECKS, 0, "Discarding passive service check result because passive checks are disabled for this service.\n");
return ERROR;
}
}
/* clear the freshening flag (it would have been set if this service was determined to be stale) */
if(queued_check_result->check_options & CHECK_OPTION_FRESHNESS_CHECK)
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)
temp_service->is_executing = FALSE;
/* DISCARD INVALID FRESHNESS CHECK RESULTS */
/* If a services goes stale, Nagios will initiate a forced check in order to freshen it. There is a race condition whereby a passive check
could arrive between the 1) initiation of the forced check and 2) the time when the forced check result is processed here. This would
make the service fresh again, so we do a quick check to make sure the service is still stale before we accept the check result. */
if((queued_check_result->check_options & CHECK_OPTION_FRESHNESS_CHECK) && is_service_result_fresh(temp_service, current_time, FALSE) == TRUE) {
log_debug_info(DEBUGL_CHECKS, 0, "Discarding service freshness check result because the service is currently fresh (race condition avoided).\n");
return OK;
}
/* check latency is passed to us */
temp_service->latency = queued_check_result->latency;
/* update the execution time for this check (millisecond resolution) */
temp_service->execution_time = (double)((double)(queued_check_result->finish_time.tv_sec - queued_check_result->start_time.tv_sec) + (double)((queued_check_result->finish_time.tv_usec - queued_check_result->start_time.tv_usec) / 1000.0) / 1000.0);
if(temp_service->execution_time < 0.0)
temp_service->execution_time = 0.0;
/* get the last check time */
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;
/* update check statistics for passive checks */
if(queued_check_result->check_type == SERVICE_CHECK_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... */
reschedule_check = queued_check_result->reschedule_check;
/* save the old service status info */
temp_service->last_state = temp_service->current_state;
/* save old plugin output */
if(temp_service->plugin_output)
old_plugin_output = (char *)strdup(temp_service->plugin_output);
/* clear the old plugin output and perf data buffers */
my_free(temp_service->plugin_output);
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) {
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);
temp_service->plugin_output = (char *)strdup("(Service check did not exit properly)");
temp_service->current_state = 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, "\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) {
case STATE_OK:
temp_service->last_time_ok = temp_service->last_check;
break;
case STATE_WARNING:
temp_service->last_time_warning = temp_service->last_check;
break;
case STATE_UNKNOWN:
temp_service->last_time_unknown = temp_service->last_check;
break;
case STATE_CRITICAL:
temp_service->last_time_critical = temp_service->last_check;
break;
default:
break;
}
/* 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(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);
}
/* get the host that this service runs on */
temp_host = (host *)temp_service->host_ptr;
/* if the service check was okay... */
if(temp_service->current_state == STATE_OK) {
/* if the host has never been checked before, verify its status */
/* only do this if 1) the initial state was set to non-UP or 2) the host is not scheduled to be checked soon (next 5 minutes) */
if(temp_host->has_been_checked == FALSE && (temp_host->initial_state != HOST_UP || (unsigned long)temp_host->next_check == 0L || (unsigned long)(temp_host->next_check - current_time) > 300)) {
/* 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);
}
}
/**** 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;
log_debug_info(DEBUGL_CHECKS, 2, "ST: %s CA: %d MA: %d CS: %d LS: %d LHS: %d\n", (temp_service->state_type == SOFT_STATE) ? "SOFT" : "HARD", temp_service->current_attempt, temp_service->max_attempts, temp_service->current_state, temp_service->last_state, temp_service->last_hard_state);
/* check for a state change (either soft or hard) */
if(temp_service->current_state != temp_service->last_state) {
log_debug_info(DEBUGL_CHECKS, 2, "Service has changed state since last check!\n");
state_change = TRUE;
}
/* checks for a hard state change where host was down at last service check */
/* this occurs in the case where host goes down and service current attempt gets reset to 1 */
/* if this check is not made, the service recovery looks like a soft recovery instead of a hard one */
if(temp_service->host_problem_at_last_check == TRUE && temp_service->current_state == STATE_OK) {
log_debug_info(DEBUGL_CHECKS, 2, "Service had a HARD STATE CHANGE!!\n");
hard_state_change = TRUE;
}
/* check for a "normal" hard state change where max check attempts is reached */
if(temp_service->current_attempt >= temp_service->max_attempts && temp_service->current_state != temp_service->last_hard_state) {
log_debug_info(DEBUGL_CHECKS, 2, "Service had a HARD STATE CHANGE!!\n");
hard_state_change = TRUE;
}
/* a state change occurred... */
/* reset last and next notification times and acknowledgement flag if necessary, misc other stuff */
if(state_change == TRUE || hard_state_change == TRUE) {
/* reschedule the service check */
reschedule_check = TRUE;
/* reset notification times */
temp_service->last_notification = (time_t)0;
temp_service->next_notification = (time_t)0;
/* reset notification suppression option */
temp_service->no_more_notifications = FALSE;
if(temp_service->acknowledgement_type == ACKNOWLEDGEMENT_NORMAL && (state_change == TRUE || hard_state_change == FALSE)) {
temp_service->problem_has_been_acknowledged = FALSE;
temp_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE;
/* remove any non-persistant comments associated with the ack */
delete_service_acknowledgement_comments(temp_service);
}
else if(temp_service->acknowledgement_type == ACKNOWLEDGEMENT_STICKY && temp_service->current_state == STATE_OK) {
temp_service->problem_has_been_acknowledged = FALSE;
temp_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE;
/* remove any non-persistant comments associated with the ack */
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;*/
}
/* initialize the last host and service state change times if necessary */
if(temp_service->last_state_change == (time_t)0)
temp_service->last_state_change = temp_service->last_check;
if(temp_service->last_hard_state_change == (time_t)0)
temp_service->last_hard_state_change = temp_service->last_check;
if(temp_host->last_state_change == (time_t)0)
temp_host->last_state_change = temp_service->last_check;
if(temp_host->last_hard_state_change == (time_t)0)
temp_host->last_hard_state_change = temp_service->last_check;
/* update last service state change times */
if(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;
/* update the event and problem ids */
if(state_change == TRUE) {
/* always update the event id on a state change */
temp_service->last_event_id = temp_service->current_event_id;
temp_service->current_event_id = next_event_id;
next_event_id++;
/* 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++;
}
/* clear the problem id when transitioning from a problem state to an OK state */
if(temp_service->current_state == STATE_OK) {
temp_service->last_problem_id = temp_service->current_problem_id;
temp_service->current_problem_id = 0L;
}
}
/**************************************/
/******* SERVICE CHECK OK LOGIC *******/
/**************************************/
/* if the service is up and running OK... */
if(temp_service->current_state == STATE_OK) {
log_debug_info(DEBUGL_CHECKS, 1, "Service is OK.\n");
/* reset the acknowledgement flag (this should already have been done, but just in case...) */
temp_service->problem_has_been_acknowledged = FALSE;
temp_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE;
/* verify the route to the host and send out host recovery notifications */
if(temp_host->current_state != HOST_UP) {
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)
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? */
/* usually 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)) {
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 */
else
run_async_host_check_3x(temp_host, CHECK_OPTION_NONE, 0.0, FALSE, FALSE, NULL, NULL);
}
}
/* if a hard service recovery has occurred... */
if(hard_state_change == TRUE) {
log_debug_info(DEBUGL_CHECKS, 1, "Service experienced a HARD RECOVERY.\n");
/* set the state type macro */
temp_service->state_type = HARD_STATE;
/* log the service recovery */
log_service_event(temp_service);
state_was_logged = TRUE;
/* 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);
check_for_host_flapping(temp_host, TRUE, FALSE, TRUE);
flapping_check_done = TRUE;
/* notify contacts about the service recovery */
service_notification(temp_service, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* run the service event handler to handle the hard state change */
handle_service_event(temp_service);
}
/* else if a soft service recovery has occurred... */
else if(state_change == TRUE) {
log_debug_info(DEBUGL_CHECKS, 1, "Service experienced a SOFT RECOVERY.\n");
/* this is a soft recovery */
temp_service->state_type = SOFT_STATE;
/* log the soft recovery */
log_service_event(temp_service);
state_was_logged = TRUE;
/* run the service event handler to handle the soft state change */
handle_service_event(temp_service);
}
/* else no service state change has occurred... */
else {
log_debug_info(DEBUGL_CHECKS, 1, "Service did not change state.\n");
}
/* should we obsessive over service checks? */
if(obsess_over_services == TRUE)
obsessive_compulsive_service_check_processor(temp_service);
/* reset all service variables because its okay now... */
temp_service->host_problem_at_last_check = FALSE;
temp_service->current_attempt = 1;
temp_service->state_type = HARD_STATE;
temp_service->last_hard_state = STATE_OK;
temp_service->last_notification = (time_t)0;
temp_service->next_notification = (time_t)0;
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;
if(reschedule_check == TRUE)
next_service_check = (time_t)(temp_service->last_check + (temp_service->check_interval * interval_length));
}
/*******************************************/
/******* SERVICE CHECK PROBLEM LOGIC *******/
/*******************************************/
/* hey, something's not working quite like it should... */
else {
log_debug_info(DEBUGL_CHECKS, 1, "Service is in a non-OK state!\n");
/* check the route to the host if its up right now... */
if(temp_host->current_state == HOST_UP) {
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);
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);
}
}
}
/* 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");
/* 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);
}
/* 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 */
if(temp_host->has_been_checked == FALSE) {
temp_host->has_been_checked = TRUE;
temp_host->last_check = temp_service->last_check;
}
/* fake the route check result */
route_result = temp_host->current_state;
/* possibly re-send host notifications... */
host_notification(temp_host, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
}
}
/* 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) {
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;
/* 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;
/* 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;
*/
}
/* the host is up - it recovered since the last time the service was checked... */
else if(temp_service->host_problem_at_last_check == TRUE) {
/* next time the service is checked we shouldn't get into this same case... */
temp_service->host_problem_at_last_check = FALSE;
/* reset the current check counter, so we give the service a chance */
/* this helps prevent the case where service has N max check attempts, N-1 of which have already occurred. */
/* if we didn't do this, the next check might fail and result in a hard problem - we should really give it more time */
/* ADDED IF STATEMENT 01-17-05 EG */
/* 01-17-05: Services in hard problem states before hosts went down would sometimes come back as soft problem states after */
/* the hosts recovered. This caused problems, so hopefully this will fix it */
if(temp_service->state_type == SOFT_STATE)
temp_service->current_attempt = 1;
}
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(temp_service->current_attempt < temp_service->max_attempts) {
/* the host is down or unreachable, so don't attempt to retry the service check */
if(route_result != HOST_UP) {
log_debug_info(DEBUGL_CHECKS, 1, "Host isn't UP, so we won't retry the service check...\n");
/* the host is not up, so reschedule the next service check at regular interval */
if(reschedule_check == TRUE)
next_service_check = (time_t)(temp_service->last_check + (temp_service->check_interval * interval_length));
/* log the problem as a hard state if the host just went down */
if(hard_state_change == TRUE) {
log_service_event(temp_service);
state_was_logged = TRUE;
/* run the service event handler to handle the hard state */
handle_service_event(temp_service);
}
}
/* the host is up, so continue to retry the service check */
else {
log_debug_info(DEBUGL_CHECKS, 1, "Host is UP, so we'll retry the service check...\n");
/* this is a soft state */
temp_service->state_type = SOFT_STATE;
/* log the service check retry */
log_service_event(temp_service);
state_was_logged = TRUE;
/* run the service event handler to handle the soft state */
handle_service_event(temp_service);
if(reschedule_check == TRUE)
next_service_check = (time_t)(temp_service->last_check + (temp_service->retry_interval * interval_length));
}
/* 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)) {
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)) {
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);
}
}
}
}
/* we've reached the maximum number of service rechecks, so handle the error */
else {
log_debug_info(DEBUGL_CHECKS, 1, "Service has reached max number of rechecks, so we'll handle the error...\n");
/* this is a hard state */
temp_service->state_type = HARD_STATE;
/* if we've hard a hard state change... */
if(hard_state_change == TRUE) {
/* log the service problem (even if host is not up, which is new in 0.0.5) */
log_service_event(temp_service);
state_was_logged = TRUE;
}
/* else log the problem (again) if this service is flagged as being volatile */
else if(temp_service->is_volatile == TRUE) {
log_service_event(temp_service);
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);
check_for_host_flapping(temp_host, TRUE, FALSE, TRUE);
flapping_check_done = TRUE;
/* (re)send notifications out about this service problem if the host is up (and was at last check also) and the dependencies were okay... */
service_notification(temp_service, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* run the service event handler if we changed state from the last hard state or if this service is flagged as being volatile */
if(hard_state_change == TRUE || temp_service->is_volatile == TRUE)
handle_service_event(temp_service);
/* save the last hard state */
temp_service->last_hard_state = temp_service->current_state;
/* reschedule the next check at the regular interval */
if(reschedule_check == TRUE)
next_service_check = (time_t)(temp_service->last_check + (temp_service->check_interval * interval_length));
}
/* should we obsessive over service checks? */
if(obsess_over_services == TRUE)
obsessive_compulsive_service_check_processor(temp_service);
}
/* reschedule the next service check ONLY for active, scheduled checks */
if(reschedule_check == TRUE) {
log_debug_info(DEBUGL_CHECKS, 1, "Rescheduling next check of service at %s", ctime(&next_service_check));
/* default is to reschedule service check unless a test below fails... */
temp_service->should_be_scheduled = TRUE;
/* next check time was calculated above */
temp_service->next_check = next_service_check;
/* make sure we don't get ourselves into too much trouble... */
if(current_time > temp_service->next_check)
temp_service->next_check = current_time;
/* make sure we rescheduled the next service check at a valid time */
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;
/* services with non-recurring intervals do not get rescheduled */
if(temp_service->check_interval == 0)
temp_service->should_be_scheduled = FALSE;
/* services with active checks disabled do not get rescheduled */
if(temp_service->checks_enabled == FALSE)
temp_service->should_be_scheduled = FALSE;
/* schedule a non-forced check if we can */
if(temp_service->should_be_scheduled == TRUE)
schedule_service_check(temp_service, temp_service->next_check, CHECK_OPTION_NONE);
}
/* 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))
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);
#endif
/* set the checked flag */
temp_service->has_been_checked = TRUE;
/* update the current service status log */
update_service_status(temp_service, FALSE);
/* check to see if the service and/or associate host is flapping */
if(flapping_check_done == FALSE) {
check_for_service_flapping(temp_service, TRUE, TRUE);
check_for_host_flapping(temp_host, TRUE, FALSE, TRUE);
}
/* update service performance info */
update_service_performance_data(temp_service);
/* free allocated memory */
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;
}
/* 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");
if(svc == NULL)
return;
log_debug_info(DEBUGL_CHECKS, 0, "Scheduling a %s, active check of service '%s' on host '%s' @ %s", (options & CHECK_OPTION_FORCE_EXECUTION) ? "forced" : "non-forced", svc->description, svc->host_name, ctime(&check_time));
/* don't schedule a check if active checks of this service are disabled */
if(svc->checks_enabled == FALSE && !(options & CHECK_OPTION_FORCE_EXECUTION)) {
log_debug_info(DEBUGL_CHECKS, 0, "Active checks of this service are disabled.\n");
return;
}
/* default is to use the new event */
use_original_event = FALSE;
temp_event = (timed_event *)svc->next_check_event;
/*
* If the service already has a check scheduled,
* we need to decide which of the events to use
*/
if(temp_event != NULL) {
log_debug_info(DEBUGL_CHECKS, 2, "Found another service check event for this service @ %s", ctime(&temp_event->run_time));
/* use the originally scheduled check unless we decide otherwise */
use_original_event = TRUE;
/* the original event is a forced check... */
if((temp_event->event_options & CHECK_OPTION_FORCE_EXECUTION)) {
/* the new event is also forced and its execution time is earlier than the original, so use it instead */
if((options & CHECK_OPTION_FORCE_EXECUTION) && (check_time < temp_event->run_time)) {
use_original_event = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "New service check event is forced and occurs before the existing event, so the new event will be used instead.\n");
}
}
/* the original event is not a forced check... */
else {
/* the new event is a forced check, so use it instead */
if((options & CHECK_OPTION_FORCE_EXECUTION)) {
use_original_event = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "New service check event is forced, so it will be used instead of the existing event.\n");
}
/* the new event is not forced either and its execution time is earlier than the original, so use it instead */
else if(check_time < temp_event->run_time) {
use_original_event = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "New service check event occurs before the existing (older) event, so it will be used instead.\n");
}
/* the new event is older, so override the existing one */
else {
log_debug_info(DEBUGL_CHECKS, 2, "New service check event occurs after the existing event, so we'll ignore it.\n");
}
}
}
/* 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 */
if(temp_event) {
remove_event(temp_event, &event_list_low, &event_list_low_tail);
my_free(temp_event);
}
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 = 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);
}
else {
/* reset the next check time (it may be out of sync) */
if(temp_event != NULL)
svc->next_check = temp_event->run_time;
log_debug_info(DEBUGL_CHECKS, 2, "Keeping original service check event (ignoring the new one).\n");
}
/* update the status log */
update_service_status(svc, FALSE);
return;
}
/* checks viability of performing a service check */
int check_service_check_viability(service *svc, 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_service_check_viability()\n");
/* make sure we have a service */
if(svc == NULL)
return ERROR;
/* get the check interval to use if we need to reschedule the check */
if(svc->state_type == SOFT_STATE && svc->current_state != STATE_OK)
check_interval = (svc->retry_interval * interval_length);
else
check_interval = (svc->check_interval * interval_length);
/* get the current time */
time(¤t_time);
/* initialize the next preferred check time */
preferred_time = current_time;
/* can we check the host right now? */
if(!(check_options & CHECK_OPTION_FORCE_EXECUTION)) {
/* if checks of the service are currently disabled... */
if(svc->checks_enabled == FALSE) {
preferred_time = current_time + check_interval;
perform_check = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "Active checks of the service are currently disabled.\n");
}
/* make sure this is a valid time to check the service */
if(check_time_against_period((unsigned long)current_time, svc->check_period_ptr) == ERROR) {
preferred_time = current_time;
if(time_is_valid)
*time_is_valid = FALSE;
perform_check = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "This is not a valid time for this service to be actively checked.\n");
}
/* check service dependencies for execution */
if(check_service_dependencies(svc, EXECUTION_DEPENDENCY) == DEPENDENCIES_FAILED) {
preferred_time = current_time + check_interval;
perform_check = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "Execution dependencies for this service failed, so it will not be actively checked.\n");
}
}
/* pass back the next viable check time */
if(new_time)
*new_time = preferred_time;
result = (perform_check == TRUE) ? OK : ERROR;
return result;
}
/* checks service dependencies */
int check_service_dependencies(service *svc, int dependency_type) {
servicedependency *temp_dependency = NULL;
service *temp_service = NULL;
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 (notification or execution) */
if(temp_dependency->dependency_type != dependency_type)
continue;
/* find the service we depend on... */
if((temp_service = temp_dependency->master_service_ptr) == NULL)
continue;
/* skip this dependency if it has a timeperiod and the current time isn't valid */
time(¤t_time);
if(temp_dependency->dependency_period != NULL && check_time_against_period(current_time, temp_dependency->dependency_period_ptr) == ERROR)
return FALSE;
/* get the status to use (use last hard state if its currently in a soft state) */
if(temp_service->state_type == SOFT_STATE && soft_state_dependencies == FALSE)
state = temp_service->last_hard_state;
else
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)
return DEPENDENCIES_FAILED;
/* immediate dependencies ok at this point - check parent dependencies if necessary */
if(temp_dependency->inherits_parent == TRUE) {
if(check_service_dependencies(temp_service, dependency_type) != DEPENDENCIES_OK)
return DEPENDENCIES_FAILED;
}
}
return DEPENDENCIES_OK;
}
/* check for services that never returned from a check... */
void check_for_orphaned_services(void) {
service *temp_service = NULL;
time_t current_time = 0L;
time_t expected_time = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_orphaned_services()\n");
/* get the current time */
time(¤t_time);
/* check all services... */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
/* skip services that are not currently executing */
if(temp_service->is_executing == FALSE)
continue;
/* determine the time at which the check results should have come in (allow 10 minutes slack time) */
expected_time = (time_t)(temp_service->next_check + temp_service->latency + service_check_timeout + check_reaper_interval + 600);
/* this service was supposed to have executed a while ago, but for some reason the results haven't come back in... */
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);
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);
/* decrement the number of running service checks */
if(currently_running_service_checks > 0)
currently_running_service_checks--;
/* disable the executing flag */
temp_service->is_executing = FALSE;
/* schedule an immediate check of the service */
schedule_service_check(temp_service, current_time, CHECK_OPTION_ORPHAN_CHECK);
}
}
return;
}
/* check freshness of service results */
void check_service_result_freshness(void) {
service *temp_service = NULL;
time_t current_time = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_service_result_freshness()\n");
log_debug_info(DEBUGL_CHECKS, 1, "Checking the freshness of service check results...\n");
/* bail out if we're not supposed to be checking freshness */
if(check_service_freshness == FALSE) {
log_debug_info(DEBUGL_CHECKS, 1, "Service freshness checking is disabled.\n");
return;
}
/* get the current time */
time(¤t_time);
/* check all services... */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
/* skip services we shouldn't be checking for freshness */
if(temp_service->check_freshness == FALSE)
continue;
/* skip services that are currently executing (problems here will be caught by orphaned service check) */
if(temp_service->is_executing == TRUE)
continue;
/* skip services that have both active and passive checks disabled */
if(temp_service->checks_enabled == FALSE && temp_service->accept_passive_service_checks == FALSE)
continue;
/* skip services that are already being freshened */
if(temp_service->is_being_freshened == TRUE)
continue;
/* see if the time is right... */
if(check_time_against_period(current_time, temp_service->check_period_ptr) == ERROR)
continue;
/* EXCEPTION */
/* don't check freshness of services without regular check intervals if we're using auto-freshness threshold */
if(temp_service->check_interval == 0 && temp_service->freshness_threshold == 0)
continue;
/* the results for the last check of this service are stale! */
if(is_service_result_fresh(temp_service, current_time, TRUE) == FALSE) {
/* set the freshen flag */
temp_service->is_being_freshened = TRUE;
/* schedule an immediate forced check of the service */
schedule_service_check(temp_service, current_time, CHECK_OPTION_FORCE_EXECUTION | CHECK_OPTION_FRESHNESS_CHECK);
}
}
return;
}
/* tests whether or not a service's check results are fresh */
int is_service_result_fresh(service *temp_service, time_t current_time, int log_this) {
int freshness_threshold = 0;
time_t expiration_time = 0L;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
int tdays = 0;
int thours = 0;
int tminutes = 0;
int tseconds = 0;
log_debug_info(DEBUGL_CHECKS, 2, "Checking freshness of service '%s' on host '%s'...\n", temp_service->description, temp_service->host_name);
/* use user-supplied freshness threshold or auto-calculate a freshness threshold to use? */
if(temp_service->freshness_threshold == 0) {
if(temp_service->state_type == HARD_STATE || temp_service->current_state == STATE_OK)
freshness_threshold = (temp_service->check_interval * interval_length) + temp_service->latency + additional_freshness_latency;
else
freshness_threshold = (temp_service->retry_interval * interval_length) + temp_service->latency + additional_freshness_latency;
}
else
freshness_threshold = temp_service->freshness_threshold;
log_debug_info(DEBUGL_CHECKS, 2, "Freshness thresholds: service=%d, use=%d\n", temp_service->freshness_threshold, freshness_threshold);
/* calculate expiration time */
/*
* CHANGED 11/10/05 EG -
* program start is only used in expiration time calculation
* if > last check AND active checks are enabled, so active checks
* can become stale immediately upon program startup
*/
/*
* CHANGED 02/25/06 SG -
* passive checks also become stale, so remove dependence on active
* check logic
*/
if(temp_service->has_been_checked == FALSE)
expiration_time = (time_t)(event_start + freshness_threshold);
/*
* CHANGED 06/19/07 EG -
* Per Ton's suggestion (and user requests), only use program start
* time over last check if no specific threshold has been set by user.
* Problems can occur if Nagios is restarted more frequently that
* freshness threshold intervals (services never go stale).
*/
/*
* CHANGED 10/07/07 EG:
* Only match next condition for services that
* have active checks enabled...
*/
/*
* CHANGED 10/07/07 EG:
* Added max_service_check_spread to expiration time as suggested
* by Altinity
*/
else if(temp_service->checks_enabled == TRUE && event_start > temp_service->last_check && temp_service->freshness_threshold == 0)
expiration_time = (time_t)(event_start + freshness_threshold + (max_service_check_spread * interval_length));
else
expiration_time = (time_t)(temp_service->last_check + freshness_threshold);
/*
* If the check was last done passively, we assume it's going
* to continue that way and we need to handle the fact that
* Nagios might have been shut off for quite a long time. If so,
* we mustn't spam freshness notifications but use event_start
* instead of last_check to determine freshness expiration time.
* The threshold for "long time" is determined as 61.8% of the normal
* 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) {
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 */
if(expiration_time < current_time) {
get_time_breakdown((current_time - expiration_time), &days, &hours, &minutes, &seconds);
get_time_breakdown(freshness_threshold, &tdays, &thours, &tminutes, &tseconds);
/* log a warning */
if(log_this == TRUE)
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: The results of service '%s' on host '%s' are stale by %dd %dh %dm %ds (threshold=%dd %dh %dm %ds). I'm forcing an immediate check of the service.\n", temp_service->description, temp_service->host_name, days, hours, minutes, seconds, tdays, thours, tminutes, tseconds);
log_debug_info(DEBUGL_CHECKS, 1, "Check results for service '%s' on host '%s' are stale by %dd %dh %dm %ds (threshold=%dd %dh %dm %ds). Forcing an immediate check of the service...\n", temp_service->description, temp_service->host_name, days, hours, minutes, seconds, tdays, thours, tminutes, tseconds);
return FALSE;
}
log_debug_info(DEBUGL_CHECKS, 1, "Check results for service '%s' on host '%s' are fresh.\n", temp_service->description, temp_service->host_name);
return TRUE;
}
/******************************************************************/
/*************** 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;
log_debug_info(DEBUGL_FUNCTIONS, 0, "schedule_host_check()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_CHECKS, 0, "Scheduling a %s, active check of host '%s' @ %s", (options & CHECK_OPTION_FORCE_EXECUTION) ? "forced" : "non-forced", hst->name, ctime(&check_time));
/* don't schedule a check if active checks of this host are disabled */
if(hst->checks_enabled == FALSE && !(options & CHECK_OPTION_FORCE_EXECUTION)) {
log_debug_info(DEBUGL_CHECKS, 0, "Active checks are disabled for this host.\n");
return;
}
/* default is to use the new event */
use_original_event = FALSE;
temp_event = (timed_event *)hst->next_check_event;
/*
* If the host already had a check scheduled we need
* to decide which check event to use
*/
if(temp_event != NULL) {
log_debug_info(DEBUGL_CHECKS, 2, "Found another host check event for this host @ %s", ctime(&temp_event->run_time));
/* use the originally scheduled check unless we decide otherwise */
use_original_event = TRUE;
/* the original event is a forced check... */
if((temp_event->event_options & CHECK_OPTION_FORCE_EXECUTION)) {
/* the new event is also forced and its execution time is earlier than the original, so use it instead */
if((options & CHECK_OPTION_FORCE_EXECUTION) && (check_time < temp_event->run_time)) {
log_debug_info(DEBUGL_CHECKS, 2, "New host check event is forced and occurs before the existing event, so the new event be used instead.\n");
use_original_event = FALSE;
}
}
/* the original event is not a forced check... */
else {
/* the new event is a forced check, so use it instead */
if((options & CHECK_OPTION_FORCE_EXECUTION)) {
use_original_event = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "New host check event is forced, so it will be used instead of the existing event.\n");
}
/* the new event is not forced either and its execution time is earlier than the original, so use it instead */
else if(check_time < temp_event->run_time) {
use_original_event = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "New host check event occurs before the existing (older) event, so it will be used instead.\n");
}
/* the new event is older, so override the existing one */
else {
log_debug_info(DEBUGL_CHECKS, 2, "New host check event occurs after the existing event, so we'll ignore it.\n");
}
}
}
/* use the new event */
if(use_original_event == FALSE) {
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) {
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 = 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);
}
else {
/* reset the next check time (it may be out of sync) */
if(temp_event != NULL)
hst->next_check = temp_event->run_time;
log_debug_info(DEBUGL_CHECKS, 2, "Keeping original host check event (ignoring the new one).\n");
}
/* update the status log */
update_host_status(hst, FALSE);
return;
}
/* checks host dependencies */
int check_host_dependencies(host *hst, int dependency_type) {
hostdependency *temp_dependency = NULL;
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)) {
/* only check dependencies of the desired type (notification or execution) */
if(temp_dependency->dependency_type != dependency_type)
continue;
/* find the host we depend on... */
if((temp_host = temp_dependency->master_host_ptr) == NULL)
continue;
/* skip this dependency if it has a timeperiod and the current time isn't valid */
time(¤t_time);
if(temp_dependency->dependency_period != NULL && check_time_against_period(current_time, temp_dependency->dependency_period_ptr) == ERROR)
return FALSE;
/* get the status to use (use last hard state if its currently in a soft state) */
if(temp_host->state_type == SOFT_STATE && soft_state_dependencies == FALSE)
state = temp_host->last_hard_state;
else
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)
return DEPENDENCIES_FAILED;
/* immediate dependencies ok at this point - check parent dependencies if necessary */
if(temp_dependency->inherits_parent == TRUE) {
if(check_host_dependencies(temp_host, dependency_type) != DEPENDENCIES_OK)
return DEPENDENCIES_FAILED;
}
}
return DEPENDENCIES_OK;
}
/* check for hosts that never returned from a check... */
void check_for_orphaned_hosts(void) {
host *temp_host = NULL;
time_t current_time = 0L;
time_t expected_time = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_orphaned_hosts()\n");
/* get the current time */
time(¤t_time);
/* check all hosts... */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
/* skip hosts that don't have a set check interval (on-demand checks are missed by the orphan logic) */
if(temp_host->next_check == (time_t)0L)
continue;
/* skip hosts that are not currently executing */
if(temp_host->is_executing == FALSE)
continue;
/* determine the time at which the check results should have come in (allow 10 minutes slack time) */
expected_time = (time_t)(temp_host->next_check + temp_host->latency + host_check_timeout + check_reaper_interval + 600);
/* this host was supposed to have executed a while ago, but for some reason the results haven't come back in... */
if(expected_time < current_time) {
/* log a warning */
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: The check of host '%s' looks like it was orphaned (results never came back). I'm scheduling an immediate check of the host...\n", temp_host->name);
log_debug_info(DEBUGL_CHECKS, 1, "Host '%s' was orphaned, so we're scheduling an immediate check...\n", temp_host->name);
/* decrement the number of running host checks */
if(currently_running_host_checks > 0)
currently_running_host_checks--;
/* disable the executing flag */
temp_host->is_executing = FALSE;
/* schedule an immediate check of the host */
schedule_host_check(temp_host, current_time, CHECK_OPTION_ORPHAN_CHECK);
}
}
return;
}
/* check freshness of host results */
void check_host_result_freshness(void) {
host *temp_host = NULL;
time_t current_time = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_host_result_freshness()\n");
log_debug_info(DEBUGL_CHECKS, 2, "Attempting to check the freshness of host check results...\n");
/* bail out if we're not supposed to be checking freshness */
if(check_host_freshness == FALSE) {
log_debug_info(DEBUGL_CHECKS, 2, "Host freshness checking is disabled.\n");
return;
}
/* get the current time */
time(¤t_time);
/* check all hosts... */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
/* skip hosts we shouldn't be checking for freshness */
if(temp_host->check_freshness == FALSE)
continue;
/* skip hosts that have both active and passive checks disabled */
if(temp_host->checks_enabled == FALSE && temp_host->accept_passive_host_checks == FALSE)
continue;
/* skip hosts that are currently executing (problems here will be caught by orphaned host check) */
if(temp_host->is_executing == TRUE)
continue;
/* skip hosts that are already being freshened */
if(temp_host->is_being_freshened == TRUE)
continue;
/* see if the time is right... */
if(check_time_against_period(current_time, temp_host->check_period_ptr) == ERROR)
continue;
/* the results for the last check of this host are stale */
if(is_host_result_fresh(temp_host, current_time, TRUE) == FALSE) {
/* set the freshen flag */
temp_host->is_being_freshened = TRUE;
/* schedule an immediate forced check of the host */
schedule_host_check(temp_host, current_time, CHECK_OPTION_FORCE_EXECUTION | CHECK_OPTION_FRESHNESS_CHECK);
}
}
return;
}
/* checks to see if a hosts's check results are fresh */
int is_host_result_fresh(host *temp_host, time_t current_time, int log_this) {
time_t expiration_time = 0L;
int freshness_threshold = 0;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
int tdays = 0;
int thours = 0;
int tminutes = 0;
int tseconds = 0;
double interval = 0;
log_debug_info(DEBUGL_CHECKS, 2, "Checking freshness of host '%s'...\n", temp_host->name);
/* use user-supplied freshness threshold or auto-calculate a freshness threshold to use? */
if(temp_host->freshness_threshold == 0) {
if(temp_host->state_type == HARD_STATE || temp_host->current_state == STATE_OK) {
interval = temp_host->check_interval;
}
else {
interval = temp_host->retry_interval;
}
freshness_threshold = (interval * interval_length) + temp_host->latency + additional_freshness_latency;
}
else
freshness_threshold = temp_host->freshness_threshold;
log_debug_info(DEBUGL_CHECKS, 2, "Freshness thresholds: host=%d, use=%d\n", temp_host->freshness_threshold, freshness_threshold);
/* calculate expiration time */
/*
* CHANGED 11/10/05 EG:
* program start is only used in expiration time calculation
* if > last check AND active checks are enabled, so active checks
* can become stale immediately upon program startup
*/
if(temp_host->has_been_checked == FALSE)
expiration_time = (time_t)(event_start + freshness_threshold);
/*
* CHANGED 06/19/07 EG:
* Per Ton's suggestion (and user requests), only use program start
* time over last check if no specific threshold has been set by user.
* Problems can occur if Nagios is restarted more frequently that
* freshness threshold intervals (hosts never go stale).
*/
/*
* CHANGED 10/07/07 EG:
* Added max_host_check_spread to expiration time as suggested by
* Altinity
*/
else if(temp_host->checks_enabled == TRUE && event_start > temp_host->last_check && temp_host->freshness_threshold == 0)
expiration_time = (time_t)(event_start + freshness_threshold + (max_host_check_spread * interval_length));
else
expiration_time = (time_t)(temp_host->last_check + freshness_threshold);
/*
* If the check was last done passively, we assume it's going
* to continue that way and we need to handle the fact that
* Nagios might have been shut off for quite a long time. If so,
* we mustn't spam freshness notifications but use event_start
* instead of last_check to determine freshness expiration time.
* The threshold for "long time" is determined as 61.8% of the normal
* 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) {
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);
/* the results for the last check of this host are stale */
if(expiration_time < current_time) {
get_time_breakdown((current_time - expiration_time), &days, &hours, &minutes, &seconds);
get_time_breakdown(freshness_threshold, &tdays, &thours, &tminutes, &tseconds);
/* log a warning */
if(log_this == TRUE)
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: The results of host '%s' are stale by %dd %dh %dm %ds (threshold=%dd %dh %dm %ds). I'm forcing an immediate check of the host.\n", temp_host->name, days, hours, minutes, seconds, tdays, thours, tminutes, tseconds);
log_debug_info(DEBUGL_CHECKS, 1, "Check results for host '%s' are stale by %dd %dh %dm %ds (threshold=%dd %dh %dm %ds). Forcing an immediate check of the host...\n", temp_host->name, days, hours, minutes, seconds, tdays, thours, tminutes, tseconds);
return FALSE;
}
else
log_debug_info(DEBUGL_CHECKS, 1, "Check results for host '%s' are fresh.\n", temp_host->name);
return TRUE;
}
/******************************************************************/
/************* 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 result = OK;
time_t current_time = 0L;
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
int time_is_valid = TRUE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_scheduled_host_check_3x()\n");
if(hst == NULL)
return ERROR;
log_debug_info(DEBUGL_CHECKS, 0, "Attempting to run scheduled check of host '%s': check options=%d, latency=%lf\n", hst->name, check_options, latency);
/*
* reset the next_check_event so we know this host
* check is no longer in the scheduling queue
*/
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);
/* an error occurred, so reschedule the check */
if(result == ERROR) {
log_debug_info(DEBUGL_CHECKS, 1, "Unable to run scheduled host check at this time\n");
/* only attempt to (re)schedule checks that should get checked... */
if(hst->should_be_scheduled == TRUE) {
/* get current time */
time(¤t_time);
/* determine next time we should check the host if needed */
/* if host has no check interval, schedule it again for 5 minutes from now */
if(current_time >= preferred_time)
preferred_time = current_time + ((hst->check_interval <= 0) ? 300 : (hst->check_interval * interval_length));
/* 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) {
/*
hst->next_check=(time_t)(next_valid_time+(60*60*24*365));
hst->should_be_scheduled=FALSE;
*/
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);
log_debug_info(DEBUGL_CHECKS, 1, "Unable to find any valid times to reschedule the next host check!\n");
}
/* this service could be rescheduled... */
else {
hst->next_check = next_valid_time;
hst->should_be_scheduled = TRUE;
log_debug_info(DEBUGL_CHECKS, 1, "Rescheduled next host check for %s", ctime(&next_valid_time));
}
}
/* update the status log */
update_host_status(hst, FALSE);
/* reschedule the next host check - unless we couldn't find a valid next check time */
/* 10/19/07 EG - keep original check options */
if(hst->should_be_scheduled == TRUE)
schedule_host_check(hst, hst->next_check, check_options);
return ERROR;
}
return OK;
}
/* 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) {
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;
#ifdef USE_EVENT_BROKER
int neb_result = OK;
#endif
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_async_host_check_3x()\n");
/* make sure we have a host */
if(hst == NULL)
return ERROR;
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;
/* 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");
return ERROR;
}
/******** GOOD TO GO FOR A REAL HOST CHECK AT THIS POINT ********/
#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_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 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)
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! */
if(neb_result == NEBERROR_CALLBACKOVERRIDE)
return OK;
#endif
log_debug_info(DEBUGL_CHECKS, 0, "Checking host '%s'...\n", hst->name);
/* clear check options - we don't want old check options retained */
/* only clear options if this was a scheduled check - on demand check options shouldn't affect retained info */
if(scheduled_check == TRUE)
hst->check_options = CHECK_OPTION_NONE;
/* adjust host check attempt */
adjust_host_check_attempt_3x(hst, TRUE);
/* set latency (temporarily) for macros and event broker */
old_latency = hst->latency;
hst->latency = latency;
/* grab the host macro variables */
memset(&mac, 0, sizeof(mac));
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);
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);
return ERROR;
}
/* process any macros contained in the argument */
process_macros_r(&mac, raw_command, &processed_command, 0);
my_free(raw_command);
if(processed_command == NULL) {
clear_volatile_macros_r(&mac);
log_debug_info(DEBUGL_CHECKS, 0, "Processed check command for host '%s' was NULL - aborting.\n", hst->name);
return ERROR;
}
/* 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);
/* 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);
#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);
#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);
/* fork a child process */
pid = fork();
/* an error occurred while trying to fork */
if(pid == -1) {
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;
}
/* process results of an asynchronous host check */
int handle_async_host_check_result_3x(host *temp_host, check_result *queued_check_result) {
time_t current_time;
int result = STATE_OK;
int reschedule_check = FALSE;
char *old_plugin_output = NULL;
char *temp_ptr = NULL;
struct timeval start_time_hires;
struct timeval end_time_hires;
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_async_host_check_result_3x()\n");
/* make sure we have what we need */
if(temp_host == NULL || queued_check_result == NULL)
return ERROR;
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, 2, "\tCheck Type: %s\n", (queued_check_result->check_type == HOST_CHECK_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");
log_debug_info(DEBUGL_CHECKS, 2, "\tExited OK?: %s\n", (queued_check_result->exited_ok == TRUE) ? "Yes" : "No");
log_debug_info(DEBUGL_CHECKS, 2, "\tExec Time: %.3f\n", temp_host->execution_time);
log_debug_info(DEBUGL_CHECKS, 2, "\tLatency: %.3f\n", temp_host->latency);
log_debug_info(DEBUGL_CHECKS, 2, "\tReturn Status: %d\n", queued_check_result->return_code);
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)
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(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) {
log_debug_info(DEBUGL_CHECKS, 0, "Discarding passive host check result because passive checks are disabled for this host.\n");
return ERROR;
}
}
/* clear the freshening flag (it would have been set if this host was determined to be stale) */
if(queued_check_result->check_options & CHECK_OPTION_FRESHNESS_CHECK)
temp_host->is_being_freshened = FALSE;
/* DISCARD INVALID FRESHNESS CHECK RESULTS */
/* If a host goes stale, Nagios will initiate a forced check in order to freshen it. There is a race condition whereby a passive check
could arrive between the 1) initiation of the forced check and 2) the time when the forced check result is processed here. This would
make the host fresh again, so we do a quick check to make sure the host is still stale before we accept the check result. */
if((queued_check_result->check_options & CHECK_OPTION_FRESHNESS_CHECK) && is_host_result_fresh(temp_host, current_time, FALSE) == TRUE) {
log_debug_info(DEBUGL_CHECKS, 0, "Discarding host freshness check result because the host is currently fresh (race condition avoided).\n");
return OK;
}
/* was this check passive or active? */
temp_host->check_type = (queued_check_result->check_type == HOST_CHECK_ACTIVE) ? HOST_CHECK_ACTIVE : HOST_CHECK_PASSIVE;
/* update check statistics for passive results */
if(queued_check_result->check_type == HOST_CHECK_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... */
reschedule_check = queued_check_result->reschedule_check;
/* check latency is passed to us for both active and passive checks */
temp_host->latency = queued_check_result->latency;
/* update the execution time for this check (millisecond resolution) */
temp_host->execution_time = (double)((double)(queued_check_result->finish_time.tv_sec - queued_check_result->start_time.tv_sec) + (double)((queued_check_result->finish_time.tv_usec - queued_check_result->start_time.tv_usec) / 1000.0) / 1000.0);
if(temp_host->execution_time < 0.0)
temp_host->execution_time = 0.0;
/* set the checked flag */
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)
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;
/* save the old host state */
temp_host->last_state = temp_host->current_state;
if(temp_host->state_type == HARD_STATE)
temp_host->last_hard_state = temp_host->current_state;
/* save old plugin output */
if(temp_host->plugin_output)
old_plugin_output = (char *)strdup(temp_host->plugin_output);
/* clear the old plugin output and perf data buffers */
my_free(temp_host->plugin_output);
my_free(temp_host->long_plugin_output);
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);
/* make sure we have some data */
if(temp_host->plugin_output == NULL || !strcmp(temp_host->plugin_output, "")) {
my_free(temp_host->plugin_output);
temp_host->plugin_output = (char *)strdup("(No output returned from host check)");
}
/* replace semicolons in plugin output (but not performance data) with colons */
if((temp_ptr = temp_host->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_host->plugin_output == NULL) ? "NULL" : temp_host->plugin_output);
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;
}
}
/* 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 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;
/* OK states means the host is UP */
if(result == STATE_OK)
result = HOST_UP;
/* any problem state indicates the host is not UP */
else
result = HOST_DOWN;
}
/******************* 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);
/* free memory */
my_free(old_plugin_output);
log_debug_info(DEBUGL_CHECKS, 1, "** Async check result for host '%s' handled: new state=%d\n", temp_host->name, temp_host->current_state);
/* high resolution start time for event broker */
start_time_hires = queued_check_result->start_time;
/* high resolution end time for event broker */
gettimeofday(&end_time_hires, NULL);
#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);
#endif
return OK;
}
/* 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) {
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_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);
/* get the current time */
time(¤t_time);
/* default next check time */
next_check = (unsigned long)(current_time + (hst->check_interval * interval_length));
/* 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);
/* 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(log_passive_checks == TRUE)
logit(NSLOG_PASSIVE_CHECK, FALSE, "PASSIVE HOST CHECK: %s;%d;%s\n", hst->name, new_state, hst->plugin_output);
}
/******* HOST WAS DOWN/UNREACHABLE INITIALLY *******/
if(hst->current_state != HOST_UP) {
log_debug_info(DEBUGL_CHECKS, 1, "Host was DOWN/UNREACHABLE.\n");
/***** HOST IS NOW UP *****/
/* the host just recovered! */
if(new_state == HOST_UP) {
/* set the current state */
hst->current_state = HOST_UP;
/* 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))
hst->state_type = HARD_STATE;
else
hst->state_type = SOFT_STATE;
log_debug_info(DEBUGL_CHECKS, 1, "Host experienced a %s recovery (it's now UP).\n", (hst->state_type == HARD_STATE) ? "HARD" : "SOFT");
/* reschedule the next check of the host at the normal interval */
reschedule_check = TRUE;
next_check = (unsigned long)(current_time + (hst->check_interval * interval_length));
/* 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;
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);
}
}
/* 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;
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);
}
}
}
/***** 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");
/* passive checks are treated as HARD states by default... */
if(hst->check_type == HOST_CHECK_PASSIVE && passive_host_checks_are_soft == FALSE) {
/* set the state type */
hst->state_type = HARD_STATE;
/* reset the current attempt */
hst->current_attempt = 1;
}
/* active checks and passive checks (treated as SOFT states) */
else {
/* set the state type */
/* we've maxed out on the retries */
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)
hst->state_type = HARD_STATE;
/* the host is in a soft state and the check will be retried */
else
hst->state_type = SOFT_STATE;
}
/* 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)
hst->current_state = determine_host_reachability(hst);
/* reschedule the next check if the host state changed */
if(hst->last_state != hst->current_state || hst->last_hard_state != hst->current_state) {
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->state_type == SOFT_STATE)
next_check = (unsigned long)(current_time + (hst->retry_interval * interval_length));
/* host has maxed out on retries (or was previously in a hard problem state), so reschedule the next check at the normal interval */
else
next_check = (unsigned long)(current_time + (hst->check_interval * interval_length));
}
}
}
/******* HOST WAS UP INITIALLY *******/
else {
log_debug_info(DEBUGL_CHECKS, 1, "Host was UP.\n");
/***** HOST IS STILL UP *****/
/* either the host never went down since last check */
if(new_state == HOST_UP) {
log_debug_info(DEBUGL_CHECKS, 1, "Host is still UP.\n");
/* set the current state */
hst->current_state = HOST_UP;
/* set the state type */
hst->state_type = HARD_STATE;
/* reschedule the next check at the normal interval */
if(reschedule_check == TRUE)
next_check = (unsigned long)(current_time + (hst->check_interval * interval_length));
}
/***** HOST IS NOW DOWN/UNREACHABLE *****/
else {
log_debug_info(DEBUGL_CHECKS, 1, "Host is now DOWN/UNREACHABLE.\n");
/***** SPECIAL CASE FOR HOSTS WITH MAX_ATTEMPTS==1 *****/
if(hst->max_attempts == 1) {
log_debug_info(DEBUGL_CHECKS, 1, "Max attempts = 1!.\n");
/* 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;
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) {
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);
}
}
}
/***** 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;
}
/* by default, passive check results are treated as HARD states */
else {
/* set the state type */
hst->state_type = HARD_STATE;
/* 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);
}
}
/* 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);
}
}
}
}
}
}
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);
/* 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);
/******************** 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);
}
/* check to see if the associated host is flapping */
check_for_host_flapping(hst, TRUE, TRUE, TRUE);
/* reschedule the next check of the host (usually ONLY for scheduled, active checks, unless overridden above) */
if(reschedule_check == TRUE) {
log_debug_info(DEBUGL_CHECKS, 1, "Rescheduling next check of host at %s", ctime(&next_check));
/* default is to reschedule host check unless a test below fails... */
hst->should_be_scheduled = TRUE;
/* get the new current time */
time(¤t_time);
/* make sure we don't get ourselves into too much trouble... */
if(current_time > next_check)
hst->next_check = current_time;
else
hst->next_check = next_check;
/* make sure we rescheduled the next service check at a valid time */
preferred_time = hst->next_check;
get_next_valid_time(preferred_time, &next_valid_time, hst->check_period_ptr);
hst->next_check = next_valid_time;
/* 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))
hst->should_be_scheduled = FALSE;
/* host with active checks disabled do not get rescheduled */
if(hst->checks_enabled == FALSE)
hst->should_be_scheduled = FALSE;
/* schedule a non-forced check if we can */
if(hst->should_be_scheduled == TRUE) {
schedule_host_check(hst, hst->next_check, CHECK_OPTION_NONE);
}
}
/* 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 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");
/* make sure we have a host */
if(hst == NULL)
return ERROR;
/* get the check interval to use if we need to reschedule the check */
if(hst->state_type == SOFT_STATE && hst->current_state != HOST_UP)
check_interval = (hst->retry_interval * interval_length);
else
check_interval = (hst->check_interval * interval_length);
/* make sure check interval is positive - otherwise use 5 minutes out for next check */
if(check_interval <= 0)
check_interval = 300;
/* get the current time */
time(¤t_time);
/* initialize the next preferred check time */
preferred_time = current_time;
/* can we check the host right now? */
if(!(check_options & CHECK_OPTION_FORCE_EXECUTION)) {
/* if checks of the host are currently disabled... */
if(hst->checks_enabled == FALSE) {
preferred_time = current_time + check_interval;
perform_check = FALSE;
}
/* 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) {
preferred_time = current_time;
if(time_is_valid)
*time_is_valid = FALSE;
perform_check = FALSE;
}
/* check host dependencies for execution */
if(check_host_dependencies(hst, EXECUTION_DEPENDENCY) == DEPENDENCIES_FAILED) {
preferred_time = current_time + check_interval;
perform_check = FALSE;
}
}
/* pass back the next viable check time */
if(new_time)
*new_time = preferred_time;
result = (perform_check == TRUE) ? OK : ERROR;
return result;
}
/* adjusts current host check attempt before a new check is performed */
int adjust_host_check_attempt_3x(host *hst, int is_active) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "adjust_host_check_attempt_3x()\n");
if(hst == NULL)
return ERROR;
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)
hst->current_attempt = 1;
/* if host is in a soft UP state, reset current attempt number (active checks only) */
else if(is_active == TRUE && hst->state_type == SOFT_STATE && hst->current_state == HOST_UP)
hst->current_attempt = 1;
/* increment current attempt number */
else if(hst->current_attempt < hst->max_attempts)
hst->current_attempt++;
log_debug_info(DEBUGL_CHECKS, 2, "New check attempt number = %d\n", hst->current_attempt);
return OK;
}
/* 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");
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);
/* 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");
}
/* host has no parents, so it is DOWN */
else if(hst->parent_hosts == NULL) {
state = HOST_DOWN;
log_debug_info(DEBUGL_CHECKS, 2, "Host has no parents, so it is DOWN.\n");
}
/* 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;
/* 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;
}
}
/* 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;
}
/******************************************************************/
/****************** HOST STATE HANDLER FUNCTIONS ******************/
/******************************************************************/
/* top level host state handler - occurs after every host check (soft/hard and active/passive) */
int handle_host_state(host *hst) {
int state_change = FALSE;
int hard_state_change = FALSE;
time_t current_time = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_host_state()\n");
/* get current time */
time(¤t_time);
/* obsess over this host check */
obsessive_compulsive_host_check_processor(hst);
/* update performance data */
update_host_performance_data(hst);
/* record latest time for current state */
switch(hst->current_state) {
case HOST_UP:
hst->last_time_up = current_time;
break;
case HOST_DOWN:
hst->last_time_down = current_time;
break;
case HOST_UNREACHABLE:
hst->last_time_unreachable = current_time;
break;
default:
break;
}
/* has the host state changed? */
if(hst->last_state != hst->current_state || (hst->current_state == HOST_UP && hst->state_type == SOFT_STATE))
state_change = TRUE;
if(hst->current_attempt >= hst->max_attempts && hst->last_hard_state != hst->current_state)
hard_state_change = TRUE;
/* if the host state has changed... */
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;
/* reset notification suppression option */
hst->no_more_notifications = FALSE;
/* reset the acknowledgement flag if necessary */
if(hst->acknowledgement_type == ACKNOWLEDGEMENT_NORMAL && (state_change == TRUE || hard_state_change == FALSE)) {
hst->problem_has_been_acknowledged = FALSE;
hst->acknowledgement_type = ACKNOWLEDGEMENT_NONE;
/* remove any non-persistant comments associated with the ack */
delete_host_acknowledgement_comments(hst);
}
else if(hst->acknowledgement_type == ACKNOWLEDGEMENT_STICKY && hst->current_state == HOST_UP) {
hst->problem_has_been_acknowledged = FALSE;
hst->acknowledgement_type = ACKNOWLEDGEMENT_NONE;
/* remove any non-persistant comments associated with the ack */
delete_host_acknowledgement_comments(hst);
}
}
/* Not sure about this, but is old behaviour */
if(hst->last_hard_state != hst->current_state)
hard_state_change = TRUE;
if(state_change == TRUE || hard_state_change == TRUE) {
/* update last state change times */
hst->last_state_change = current_time;
if(hst->state_type == HARD_STATE)
hst->last_hard_state_change = current_time;
/* update the event id */
hst->last_event_id = hst->current_event_id;
hst->current_event_id = next_event_id;
next_event_id++;
/* 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++;
}
/* clear the problem id when transitioning from a problem state to an UP state */
if(hst->current_state == HOST_UP) {
hst->last_problem_id = hst->current_problem_id;
hst->current_problem_id = 0L;
}
/* write the host state change to the main log file */
if(hst->state_type == HARD_STATE || (hst->state_type == SOFT_STATE && log_host_retries == TRUE))
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)*/
check_pending_flex_host_downtime(hst);
/* notify contacts about the recovery or problem if its a "hard" state */
if(hst->state_type == HARD_STATE)
host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* handle the host state change */
handle_host_event(hst);
/* the host just recovered, so reset the current host attempt */
if(hst->current_state == HOST_UP)
hst->current_attempt = 1;
/* 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;
}
}
/* else the host state has not changed */
else {
/* notify contacts if host is still down or unreachable */
if(hst->current_state != HOST_UP && hst->state_type == HARD_STATE)
host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* if we're in a soft state and we should log host retries, do so now... */
if(hst->state_type == SOFT_STATE && log_host_retries == TRUE)
log_host_event(hst);
}
return OK;
}
/* parse raw plugin output and return: 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;
/* initialize values */
if(short_output)
*short_output = NULL;
if(long_output)
*long_output = NULL;
if(perf_data)
*perf_data = NULL;
/* nothing to do */
if(buf == NULL || !strcmp(buf, ""))
return OK;
used_buf = strlen(buf) + 1;
/* initialize dynamic buffers (1KB chunk size) */
dbuf_init(&db1, dbuf_chunk);
dbuf_init(&db2, 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] == '\\') {
x++;
buf[y++] = buf[x];
}
else if(buf[x] == '\\' && buf[x + 1] == 'n') {
x++;
buf[y++] = '\n';
}
else
buf[y++] = buf[x];
}
buf[y] = '\x0';
}
/* process each line of input */
for(x = 0; eof == FALSE; 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;
eof = TRUE;
}
else
found_newline = FALSE;
if(found_newline == TRUE) {
current_line++;
/* 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);
}
}
/* 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;
}
/* 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;
}
}
/* save long output */
if(long_output && (db1.buf && strcmp(db1.buf, ""))) {
if(escape_newlines_please == FALSE)
*long_output = (char *)strdup(db1.buf);
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);
}
}
}
/* save perf data */
if(perf_data && (db2.buf && strcmp(db2.buf, "")))
*perf_data = (char *)strdup(db2.buf);
/* strip short output and perf data */
if(short_output)
strip(*short_output);
if(perf_data)
strip(*perf_data);
/* free dynamic buffers */
dbuf_free(&db1);
dbuf_free(&db2);
return OK;
}
nagios/base/commands.c 0000664 0000000 0000000 00000454427 12210155146 0015232 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* COMMANDS.C - External command functions for Nagios
*
* Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 11-30-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.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/comments.h"
#include "../include/downtime.h"
#include "../include/statusdata.h"
#include "../include/perfdata.h"
#include "../include/sretention.h"
#include "../include/broker.h"
#include "../include/nagios.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 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;
/******************************************************************/
/****************** EXTERNAL COMMAND PROCESSING *******************/
/******************************************************************/
/* 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;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_external_commands()\n");
/* bail out if we shouldn't be checking for external commands */
if(check_external_commands == FALSE)
return ERROR;
/* update last command check time */
last_command_check = time(NULL);
/* 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 passive check result list pointers */
passive_check_result_list = NULL;
passive_check_result_list_tail = NULL;
/* process all commands found in the buffer */
while(1) {
/* 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;
}
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();
return OK;
}
/* 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)
return ERROR;
log_debug_info(DEBUGL_EXTERNALCOMMANDS, 1, "Processing commands from file '%s'. File will %s deleted after processing.\n", fname, (delete_file == TRUE) ? "be" : "NOT be");
/* open the config file for reading */
if((thefile = mmap_fopen(fname)) == NULL) {
logit(NSLOG_INFO_MESSAGE, FALSE, "Error: Cannot open file '%s' to process external commands!", fname);
return ERROR;
}
/* process all commands in the file */
while(1) {
/* free memory */
my_free(input);
/* read the next line */
if((input = mmap_fgets(thefile)) == NULL)
break;
/* process the command */
process_external_command1(input);
}
/* close the file */
mmap_fclose(thefile);
/* delete the file */
if(delete_file == TRUE)
unlink(fname);
return OK;
}
/* top-level external command processor */
int process_external_command1(char *cmd) {
char *temp_buffer = NULL;
char *command_id = NULL;
char *args = NULL;
time_t entry_time = 0L;
int command_type = CMD_NONE;
char *temp_ptr = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "process_external_command1()\n");
if(cmd == NULL)
return ERROR;
/* strip the command of newlines and carriage returns */
strip(cmd);
log_debug_info(DEBUGL_EXTERNALCOMMANDS, 2, "Raw command entry: %s\n", cmd);
/* get the command entry time */
if((temp_ptr = my_strtok(cmd, "[")) == NULL)
return ERROR;
if((temp_ptr = my_strtok(NULL, "]")) == NULL)
return ERROR;
entry_time = (time_t)strtoul(temp_ptr, NULL, 10);
/* get the command identifier */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
if((command_id = (char *)strdup(temp_ptr + 1)) == NULL)
return ERROR;
/* get the command arguments */
if((temp_ptr = my_strtok(NULL, "\n")) == NULL)
args = (char *)strdup("");
else
args = (char *)strdup(temp_ptr);
if(args == NULL) {
my_free(command_id);
return ERROR;
}
/* decide what type of command this is... */
/**************************/
/**** PROCESS COMMANDS ****/
/**************************/
if(!strcmp(command_id, "ENTER_STANDBY_MODE") || !strcmp(command_id, "DISABLE_NOTIFICATIONS"))
command_type = CMD_DISABLE_NOTIFICATIONS;
else if(!strcmp(command_id, "ENTER_ACTIVE_MODE") || !strcmp(command_id, "ENABLE_NOTIFICATIONS"))
command_type = CMD_ENABLE_NOTIFICATIONS;
else if(!strcmp(command_id, "SHUTDOWN_PROGRAM") || !strcmp(command_id, "SHUTDOWN_PROCESS"))
command_type = CMD_SHUTDOWN_PROCESS;
else if(!strcmp(command_id, "RESTART_PROGRAM") || !strcmp(command_id, "RESTART_PROCESS"))
command_type = CMD_RESTART_PROCESS;
else if(!strcmp(command_id, "SAVE_STATE_INFORMATION"))
command_type = CMD_SAVE_STATE_INFORMATION;
else if(!strcmp(command_id, "READ_STATE_INFORMATION"))
command_type = CMD_READ_STATE_INFORMATION;
else if(!strcmp(command_id, "ENABLE_EVENT_HANDLERS"))
command_type = CMD_ENABLE_EVENT_HANDLERS;
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"))
command_type = CMD_DISABLE_PERFORMANCE_DATA;
else if(!strcmp(command_id, "START_EXECUTING_HOST_CHECKS"))
command_type = CMD_START_EXECUTING_HOST_CHECKS;
else if(!strcmp(command_id, "STOP_EXECUTING_HOST_CHECKS"))
command_type = CMD_STOP_EXECUTING_HOST_CHECKS;
else if(!strcmp(command_id, "START_EXECUTING_SVC_CHECKS"))
command_type = CMD_START_EXECUTING_SVC_CHECKS;
else if(!strcmp(command_id, "STOP_EXECUTING_SVC_CHECKS"))
command_type = CMD_STOP_EXECUTING_SVC_CHECKS;
else if(!strcmp(command_id, "START_ACCEPTING_PASSIVE_HOST_CHECKS"))
command_type = CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS;
else if(!strcmp(command_id, "STOP_ACCEPTING_PASSIVE_HOST_CHECKS"))
command_type = CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS;
else if(!strcmp(command_id, "START_ACCEPTING_PASSIVE_SVC_CHECKS"))
command_type = CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS;
else if(!strcmp(command_id, "STOP_ACCEPTING_PASSIVE_SVC_CHECKS"))
command_type = CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS;
else if(!strcmp(command_id, "START_OBSESSING_OVER_HOST_CHECKS"))
command_type = CMD_START_OBSESSING_OVER_HOST_CHECKS;
else if(!strcmp(command_id, "STOP_OBSESSING_OVER_HOST_CHECKS"))
command_type = CMD_STOP_OBSESSING_OVER_HOST_CHECKS;
else if(!strcmp(command_id, "START_OBSESSING_OVER_SVC_CHECKS"))
command_type = CMD_START_OBSESSING_OVER_SVC_CHECKS;
else if(!strcmp(command_id, "STOP_OBSESSING_OVER_SVC_CHECKS"))
command_type = CMD_STOP_OBSESSING_OVER_SVC_CHECKS;
else if(!strcmp(command_id, "ENABLE_FLAP_DETECTION"))
command_type = CMD_ENABLE_FLAP_DETECTION;
else if(!strcmp(command_id, "DISABLE_FLAP_DETECTION"))
command_type = CMD_DISABLE_FLAP_DETECTION;
else if(!strcmp(command_id, "CHANGE_GLOBAL_HOST_EVENT_HANDLER"))
command_type = CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER;
else if(!strcmp(command_id, "CHANGE_GLOBAL_SVC_EVENT_HANDLER"))
command_type = CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER;
else if(!strcmp(command_id, "ENABLE_SERVICE_FRESHNESS_CHECKS"))
command_type = CMD_ENABLE_SERVICE_FRESHNESS_CHECKS;
else if(!strcmp(command_id, "DISABLE_SERVICE_FRESHNESS_CHECKS"))
command_type = CMD_DISABLE_SERVICE_FRESHNESS_CHECKS;
else if(!strcmp(command_id, "ENABLE_HOST_FRESHNESS_CHECKS"))
command_type = CMD_ENABLE_HOST_FRESHNESS_CHECKS;
else if(!strcmp(command_id, "DISABLE_HOST_FRESHNESS_CHECKS"))
command_type = CMD_DISABLE_HOST_FRESHNESS_CHECKS;
/*******************************/
/**** HOST-RELATED COMMANDS ****/
/*******************************/
else if(!strcmp(command_id, "ADD_HOST_COMMENT"))
command_type = CMD_ADD_HOST_COMMENT;
else if(!strcmp(command_id, "DEL_HOST_COMMENT"))
command_type = CMD_DEL_HOST_COMMENT;
else if(!strcmp(command_id, "DEL_ALL_HOST_COMMENTS"))
command_type = CMD_DEL_ALL_HOST_COMMENTS;
else if(!strcmp(command_id, "DELAY_HOST_NOTIFICATION"))
command_type = CMD_DELAY_HOST_NOTIFICATION;
else if(!strcmp(command_id, "ENABLE_HOST_NOTIFICATIONS"))
command_type = CMD_ENABLE_HOST_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_HOST_NOTIFICATIONS"))
command_type = CMD_DISABLE_HOST_NOTIFICATIONS;
else if(!strcmp(command_id, "ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST"))
command_type = CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST;
else if(!strcmp(command_id, "DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST"))
command_type = CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST;
else if(!strcmp(command_id, "ENABLE_HOST_AND_CHILD_NOTIFICATIONS"))
command_type = CMD_ENABLE_HOST_AND_CHILD_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_HOST_AND_CHILD_NOTIFICATIONS"))
command_type = CMD_DISABLE_HOST_AND_CHILD_NOTIFICATIONS;
else if(!strcmp(command_id, "ENABLE_HOST_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_HOST_SVC_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_HOST_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_HOST_SVC_NOTIFICATIONS;
else if(!strcmp(command_id, "ENABLE_HOST_SVC_CHECKS"))
command_type = CMD_ENABLE_HOST_SVC_CHECKS;
else if(!strcmp(command_id, "DISABLE_HOST_SVC_CHECKS"))
command_type = CMD_DISABLE_HOST_SVC_CHECKS;
else if(!strcmp(command_id, "ENABLE_PASSIVE_HOST_CHECKS"))
command_type = CMD_ENABLE_PASSIVE_HOST_CHECKS;
else if(!strcmp(command_id, "DISABLE_PASSIVE_HOST_CHECKS"))
command_type = CMD_DISABLE_PASSIVE_HOST_CHECKS;
else if(!strcmp(command_id, "SCHEDULE_HOST_SVC_CHECKS"))
command_type = CMD_SCHEDULE_HOST_SVC_CHECKS;
else if(!strcmp(command_id, "SCHEDULE_FORCED_HOST_SVC_CHECKS"))
command_type = CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS;
else if(!strcmp(command_id, "ACKNOWLEDGE_HOST_PROBLEM"))
command_type = CMD_ACKNOWLEDGE_HOST_PROBLEM;
else if(!strcmp(command_id, "REMOVE_HOST_ACKNOWLEDGEMENT"))
command_type = CMD_REMOVE_HOST_ACKNOWLEDGEMENT;
else if(!strcmp(command_id, "ENABLE_HOST_EVENT_HANDLER"))
command_type = CMD_ENABLE_HOST_EVENT_HANDLER;
else if(!strcmp(command_id, "DISABLE_HOST_EVENT_HANDLER"))
command_type = CMD_DISABLE_HOST_EVENT_HANDLER;
else if(!strcmp(command_id, "ENABLE_HOST_CHECK"))
command_type = CMD_ENABLE_HOST_CHECK;
else if(!strcmp(command_id, "DISABLE_HOST_CHECK"))
command_type = CMD_DISABLE_HOST_CHECK;
else if(!strcmp(command_id, "SCHEDULE_HOST_CHECK"))
command_type = CMD_SCHEDULE_HOST_CHECK;
else if(!strcmp(command_id, "SCHEDULE_FORCED_HOST_CHECK"))
command_type = CMD_SCHEDULE_FORCED_HOST_CHECK;
else if(!strcmp(command_id, "SCHEDULE_HOST_DOWNTIME"))
command_type = CMD_SCHEDULE_HOST_DOWNTIME;
else if(!strcmp(command_id, "SCHEDULE_HOST_SVC_DOWNTIME"))
command_type = CMD_SCHEDULE_HOST_SVC_DOWNTIME;
else if(!strcmp(command_id, "DEL_HOST_DOWNTIME"))
command_type = CMD_DEL_HOST_DOWNTIME;
else if(!strcmp(command_id, "DEL_DOWNTIME_BY_HOST_NAME"))
command_type = CMD_DEL_DOWNTIME_BY_HOST_NAME;
else if(!strcmp(command_id, "DEL_DOWNTIME_BY_HOSTGROUP_NAME"))
command_type = CMD_DEL_DOWNTIME_BY_HOSTGROUP_NAME;
else if(!strcmp(command_id, "DEL_DOWNTIME_BY_START_TIME_COMMENT"))
command_type = CMD_DEL_DOWNTIME_BY_START_TIME_COMMENT;
else if(!strcmp(command_id, "ENABLE_HOST_FLAP_DETECTION"))
command_type = CMD_ENABLE_HOST_FLAP_DETECTION;
else if(!strcmp(command_id, "DISABLE_HOST_FLAP_DETECTION"))
command_type = CMD_DISABLE_HOST_FLAP_DETECTION;
else if(!strcmp(command_id, "START_OBSESSING_OVER_HOST"))
command_type = CMD_START_OBSESSING_OVER_HOST;
else if(!strcmp(command_id, "STOP_OBSESSING_OVER_HOST"))
command_type = CMD_STOP_OBSESSING_OVER_HOST;
else if(!strcmp(command_id, "CHANGE_HOST_EVENT_HANDLER"))
command_type = CMD_CHANGE_HOST_EVENT_HANDLER;
else if(!strcmp(command_id, "CHANGE_HOST_CHECK_COMMAND"))
command_type = CMD_CHANGE_HOST_CHECK_COMMAND;
else if(!strcmp(command_id, "CHANGE_NORMAL_HOST_CHECK_INTERVAL"))
command_type = CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL;
else if(!strcmp(command_id, "CHANGE_RETRY_HOST_CHECK_INTERVAL"))
command_type = CMD_CHANGE_RETRY_HOST_CHECK_INTERVAL;
else if(!strcmp(command_id, "CHANGE_MAX_HOST_CHECK_ATTEMPTS"))
command_type = CMD_CHANGE_MAX_HOST_CHECK_ATTEMPTS;
else if(!strcmp(command_id, "SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME"))
command_type = CMD_SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME;
else if(!strcmp(command_id, "SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME"))
command_type = CMD_SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME;
else if(!strcmp(command_id, "SET_HOST_NOTIFICATION_NUMBER"))
command_type = CMD_SET_HOST_NOTIFICATION_NUMBER;
else if(!strcmp(command_id, "CHANGE_HOST_CHECK_TIMEPERIOD"))
command_type = CMD_CHANGE_HOST_CHECK_TIMEPERIOD;
else if(!strcmp(command_id, "CHANGE_CUSTOM_HOST_VAR"))
command_type = CMD_CHANGE_CUSTOM_HOST_VAR;
else if(!strcmp(command_id, "SEND_CUSTOM_HOST_NOTIFICATION"))
command_type = CMD_SEND_CUSTOM_HOST_NOTIFICATION;
else if(!strcmp(command_id, "CHANGE_HOST_NOTIFICATION_TIMEPERIOD"))
command_type = CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD;
else if(!strcmp(command_id, "CHANGE_HOST_MODATTR"))
command_type = CMD_CHANGE_HOST_MODATTR;
/************************************/
/**** HOSTGROUP-RELATED COMMANDS ****/
/************************************/
else if(!strcmp(command_id, "ENABLE_HOSTGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_HOSTGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS;
else if(!strcmp(command_id, "ENABLE_HOSTGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_HOSTGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS;
else if(!strcmp(command_id, "ENABLE_HOSTGROUP_HOST_CHECKS"))
command_type = CMD_ENABLE_HOSTGROUP_HOST_CHECKS;
else if(!strcmp(command_id, "DISABLE_HOSTGROUP_HOST_CHECKS"))
command_type = CMD_DISABLE_HOSTGROUP_HOST_CHECKS;
else if(!strcmp(command_id, "ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS"))
command_type = CMD_ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS;
else if(!strcmp(command_id, "DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS"))
command_type = CMD_DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS;
else if(!strcmp(command_id, "ENABLE_HOSTGROUP_SVC_CHECKS"))
command_type = CMD_ENABLE_HOSTGROUP_SVC_CHECKS;
else if(!strcmp(command_id, "DISABLE_HOSTGROUP_SVC_CHECKS"))
command_type = CMD_DISABLE_HOSTGROUP_SVC_CHECKS;
else if(!strcmp(command_id, "ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS"))
command_type = CMD_ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS;
else if(!strcmp(command_id, "DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS"))
command_type = CMD_DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS;
else if(!strcmp(command_id, "SCHEDULE_HOSTGROUP_HOST_DOWNTIME"))
command_type = CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME;
else if(!strcmp(command_id, "SCHEDULE_HOSTGROUP_SVC_DOWNTIME"))
command_type = CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME;
/**********************************/
/**** SERVICE-RELATED COMMANDS ****/
/**********************************/
else if(!strcmp(command_id, "ADD_SVC_COMMENT"))
command_type = CMD_ADD_SVC_COMMENT;
else if(!strcmp(command_id, "DEL_SVC_COMMENT"))
command_type = CMD_DEL_SVC_COMMENT;
else if(!strcmp(command_id, "DEL_ALL_SVC_COMMENTS"))
command_type = CMD_DEL_ALL_SVC_COMMENTS;
else if(!strcmp(command_id, "SCHEDULE_SVC_CHECK"))
command_type = CMD_SCHEDULE_SVC_CHECK;
else if(!strcmp(command_id, "SCHEDULE_FORCED_SVC_CHECK"))
command_type = CMD_SCHEDULE_FORCED_SVC_CHECK;
else if(!strcmp(command_id, "ENABLE_SVC_CHECK"))
command_type = CMD_ENABLE_SVC_CHECK;
else if(!strcmp(command_id, "DISABLE_SVC_CHECK"))
command_type = CMD_DISABLE_SVC_CHECK;
else if(!strcmp(command_id, "ENABLE_PASSIVE_SVC_CHECKS"))
command_type = CMD_ENABLE_PASSIVE_SVC_CHECKS;
else if(!strcmp(command_id, "DISABLE_PASSIVE_SVC_CHECKS"))
command_type = CMD_DISABLE_PASSIVE_SVC_CHECKS;
else if(!strcmp(command_id, "DELAY_SVC_NOTIFICATION"))
command_type = CMD_DELAY_SVC_NOTIFICATION;
else if(!strcmp(command_id, "ENABLE_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_SVC_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_SVC_NOTIFICATIONS;
else if(!strcmp(command_id, "PROCESS_SERVICE_CHECK_RESULT"))
command_type = CMD_PROCESS_SERVICE_CHECK_RESULT;
else if(!strcmp(command_id, "PROCESS_HOST_CHECK_RESULT"))
command_type = CMD_PROCESS_HOST_CHECK_RESULT;
else if(!strcmp(command_id, "ENABLE_SVC_EVENT_HANDLER"))
command_type = CMD_ENABLE_SVC_EVENT_HANDLER;
else if(!strcmp(command_id, "DISABLE_SVC_EVENT_HANDLER"))
command_type = CMD_DISABLE_SVC_EVENT_HANDLER;
else if(!strcmp(command_id, "ENABLE_SVC_FLAP_DETECTION"))
command_type = CMD_ENABLE_SVC_FLAP_DETECTION;
else if(!strcmp(command_id, "DISABLE_SVC_FLAP_DETECTION"))
command_type = CMD_DISABLE_SVC_FLAP_DETECTION;
else if(!strcmp(command_id, "SCHEDULE_SVC_DOWNTIME"))
command_type = CMD_SCHEDULE_SVC_DOWNTIME;
else if(!strcmp(command_id, "DEL_SVC_DOWNTIME"))
command_type = CMD_DEL_SVC_DOWNTIME;
else if(!strcmp(command_id, "ACKNOWLEDGE_SVC_PROBLEM"))
command_type = CMD_ACKNOWLEDGE_SVC_PROBLEM;
else if(!strcmp(command_id, "REMOVE_SVC_ACKNOWLEDGEMENT"))
command_type = CMD_REMOVE_SVC_ACKNOWLEDGEMENT;
else if(!strcmp(command_id, "START_OBSESSING_OVER_SVC"))
command_type = CMD_START_OBSESSING_OVER_SVC;
else if(!strcmp(command_id, "STOP_OBSESSING_OVER_SVC"))
command_type = CMD_STOP_OBSESSING_OVER_SVC;
else if(!strcmp(command_id, "CHANGE_SVC_EVENT_HANDLER"))
command_type = CMD_CHANGE_SVC_EVENT_HANDLER;
else if(!strcmp(command_id, "CHANGE_SVC_CHECK_COMMAND"))
command_type = CMD_CHANGE_SVC_CHECK_COMMAND;
else if(!strcmp(command_id, "CHANGE_NORMAL_SVC_CHECK_INTERVAL"))
command_type = CMD_CHANGE_NORMAL_SVC_CHECK_INTERVAL;
else if(!strcmp(command_id, "CHANGE_RETRY_SVC_CHECK_INTERVAL"))
command_type = CMD_CHANGE_RETRY_SVC_CHECK_INTERVAL;
else if(!strcmp(command_id, "CHANGE_MAX_SVC_CHECK_ATTEMPTS"))
command_type = CMD_CHANGE_MAX_SVC_CHECK_ATTEMPTS;
else if(!strcmp(command_id, "SET_SVC_NOTIFICATION_NUMBER"))
command_type = CMD_SET_SVC_NOTIFICATION_NUMBER;
else if(!strcmp(command_id, "CHANGE_SVC_CHECK_TIMEPERIOD"))
command_type = CMD_CHANGE_SVC_CHECK_TIMEPERIOD;
else if(!strcmp(command_id, "CHANGE_CUSTOM_SVC_VAR"))
command_type = CMD_CHANGE_CUSTOM_SVC_VAR;
else if(!strcmp(command_id, "CHANGE_CUSTOM_CONTACT_VAR"))
command_type = CMD_CHANGE_CUSTOM_CONTACT_VAR;
else if(!strcmp(command_id, "SEND_CUSTOM_SVC_NOTIFICATION"))
command_type = CMD_SEND_CUSTOM_SVC_NOTIFICATION;
else if(!strcmp(command_id, "CHANGE_SVC_NOTIFICATION_TIMEPERIOD"))
command_type = CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD;
else if(!strcmp(command_id, "CHANGE_SVC_MODATTR"))
command_type = CMD_CHANGE_SVC_MODATTR;
/***************************************/
/**** SERVICEGROUP-RELATED COMMANDS ****/
/***************************************/
else if(!strcmp(command_id, "ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS;
else if(!strcmp(command_id, "ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS;
else if(!strcmp(command_id, "ENABLE_SERVICEGROUP_HOST_CHECKS"))
command_type = CMD_ENABLE_SERVICEGROUP_HOST_CHECKS;
else if(!strcmp(command_id, "DISABLE_SERVICEGROUP_HOST_CHECKS"))
command_type = CMD_DISABLE_SERVICEGROUP_HOST_CHECKS;
else if(!strcmp(command_id, "ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS"))
command_type = CMD_ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS;
else if(!strcmp(command_id, "DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS"))
command_type = CMD_DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS;
else if(!strcmp(command_id, "ENABLE_SERVICEGROUP_SVC_CHECKS"))
command_type = CMD_ENABLE_SERVICEGROUP_SVC_CHECKS;
else if(!strcmp(command_id, "DISABLE_SERVICEGROUP_SVC_CHECKS"))
command_type = CMD_DISABLE_SERVICEGROUP_SVC_CHECKS;
else if(!strcmp(command_id, "ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS"))
command_type = CMD_ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS;
else if(!strcmp(command_id, "DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS"))
command_type = CMD_DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS;
else if(!strcmp(command_id, "SCHEDULE_SERVICEGROUP_HOST_DOWNTIME"))
command_type = CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME;
else if(!strcmp(command_id, "SCHEDULE_SERVICEGROUP_SVC_DOWNTIME"))
command_type = CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME;
/**********************************/
/**** CONTACT-RELATED COMMANDS ****/
/**********************************/
else if(!strcmp(command_id, "ENABLE_CONTACT_HOST_NOTIFICATIONS"))
command_type = CMD_ENABLE_CONTACT_HOST_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_CONTACT_HOST_NOTIFICATIONS"))
command_type = CMD_DISABLE_CONTACT_HOST_NOTIFICATIONS;
else if(!strcmp(command_id, "ENABLE_CONTACT_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_CONTACT_SVC_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_CONTACT_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_CONTACT_SVC_NOTIFICATIONS;
else if(!strcmp(command_id, "CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD"))
command_type = CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD;
else if(!strcmp(command_id, "CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD"))
command_type = CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD;
else if(!strcmp(command_id, "CHANGE_CONTACT_MODATTR"))
command_type = CMD_CHANGE_CONTACT_MODATTR;
else if(!strcmp(command_id, "CHANGE_CONTACT_MODHATTR"))
command_type = CMD_CHANGE_CONTACT_MODHATTR;
else if(!strcmp(command_id, "CHANGE_CONTACT_MODSATTR"))
command_type = CMD_CHANGE_CONTACT_MODSATTR;
/***************************************/
/**** CONTACTGROUP-RELATED COMMANDS ****/
/***************************************/
else if(!strcmp(command_id, "ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS;
else if(!strcmp(command_id, "ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS;
else if(!strcmp(command_id, "DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS;
/**************************/
/****** MISC COMMANDS *****/
/**************************/
else if(!strcmp(command_id, "PROCESS_FILE"))
command_type = CMD_PROCESS_FILE;
/****************************/
/****** CUSTOM COMMANDS *****/
/****************************/
else if(command_id[0] == '_')
command_type = CMD_CUSTOM_COMMAND;
/**** UNKNOWN COMMAND ****/
else {
/* log the bad external command */
logit(NSLOG_EXTERNAL_COMMAND | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Unrecognized external command -> %s;%s\n", command_id, args);
/* free memory */
my_free(command_id);
my_free(args);
return ERROR;
}
/* update statistics for external commands */
update_check_stats(EXTERNAL_COMMAND_STATS, time(NULL));
/* log the external command */
asprintf(&temp_buffer, "EXTERNAL COMMAND: %s;%s\n", command_id, args);
if(command_type == CMD_PROCESS_SERVICE_CHECK_RESULT || command_type == CMD_PROCESS_HOST_CHECK_RESULT) {
/* passive checks are logged in checks.c as well, as some my bypass external commands by getting dropped in checkresults dir */
if(log_passive_checks == TRUE)
write_to_all_logs(temp_buffer, NSLOG_PASSIVE_CHECK);
}
else {
if(log_external_commands == TRUE)
write_to_all_logs(temp_buffer, NSLOG_EXTERNAL_COMMAND);
}
my_free(temp_buffer);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_external_command(NEBTYPE_EXTERNALCOMMAND_START, NEBFLAG_NONE, NEBATTR_NONE, command_type, entry_time, command_id, args, NULL);
#endif
/* process the command */
process_external_command2(command_type, entry_time, args);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_external_command(NEBTYPE_EXTERNALCOMMAND_END, NEBFLAG_NONE, NEBATTR_NONE, command_type, entry_time, command_id, args, NULL);
#endif
/* free memory */
my_free(command_id);
my_free(args);
return OK;
}
/* top-level processor for a single external command */
int process_external_command2(int cmd, time_t entry_time, char *args) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "process_external_command2()\n");
log_debug_info(DEBUGL_EXTERNALCOMMANDS, 1, "External Command Type: %d\n", cmd);
log_debug_info(DEBUGL_EXTERNALCOMMANDS, 1, "Command Entry Time: %lu\n", (unsigned long)entry_time);
log_debug_info(DEBUGL_EXTERNALCOMMANDS, 1, "Command Arguments: %s\n", (args == NULL) ? "" : args);
/* how shall we execute the command? */
switch(cmd) {
/***************************/
/***** SYSTEM COMMANDS *****/
/***************************/
case CMD_SHUTDOWN_PROCESS:
case CMD_RESTART_PROCESS:
cmd_signal_process(cmd, args);
break;
case CMD_SAVE_STATE_INFORMATION:
save_state_information(FALSE);
break;
case CMD_READ_STATE_INFORMATION:
read_initial_state_information();
break;
case CMD_ENABLE_NOTIFICATIONS:
enable_all_notifications();
break;
case CMD_DISABLE_NOTIFICATIONS:
disable_all_notifications();
break;
case CMD_START_EXECUTING_SVC_CHECKS:
start_executing_service_checks();
break;
case CMD_STOP_EXECUTING_SVC_CHECKS:
stop_executing_service_checks();
break;
case CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS:
start_accepting_passive_service_checks();
break;
case CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS:
stop_accepting_passive_service_checks();
break;
case CMD_START_OBSESSING_OVER_SVC_CHECKS:
start_obsessing_over_service_checks();
break;
case CMD_STOP_OBSESSING_OVER_SVC_CHECKS:
stop_obsessing_over_service_checks();
break;
case CMD_START_EXECUTING_HOST_CHECKS:
start_executing_host_checks();
break;
case CMD_STOP_EXECUTING_HOST_CHECKS:
stop_executing_host_checks();
break;
case CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS:
start_accepting_passive_host_checks();
break;
case CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS:
stop_accepting_passive_host_checks();
break;
case CMD_START_OBSESSING_OVER_HOST_CHECKS:
start_obsessing_over_host_checks();
break;
case CMD_STOP_OBSESSING_OVER_HOST_CHECKS:
stop_obsessing_over_host_checks();
break;
case CMD_ENABLE_EVENT_HANDLERS:
start_using_event_handlers();
break;
case CMD_DISABLE_EVENT_HANDLERS:
stop_using_event_handlers();
break;
case CMD_ENABLE_FLAP_DETECTION:
enable_flap_detection_routines();
break;
case CMD_DISABLE_FLAP_DETECTION:
disable_flap_detection_routines();
break;
case CMD_ENABLE_SERVICE_FRESHNESS_CHECKS:
enable_service_freshness_checks();
break;
case CMD_DISABLE_SERVICE_FRESHNESS_CHECKS:
disable_service_freshness_checks();
break;
case CMD_ENABLE_HOST_FRESHNESS_CHECKS:
enable_host_freshness_checks();
break;
case CMD_DISABLE_HOST_FRESHNESS_CHECKS:
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;
case CMD_DISABLE_PERFORMANCE_DATA:
disable_performance_data();
break;
/***************************/
/***** HOST COMMANDS *****/
/***************************/
case CMD_ENABLE_HOST_CHECK:
case CMD_DISABLE_HOST_CHECK:
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
case CMD_ENABLE_HOST_SVC_CHECKS:
case CMD_DISABLE_HOST_SVC_CHECKS:
case CMD_ENABLE_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOST_NOTIFICATIONS:
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_ENABLE_HOST_AND_CHILD_NOTIFICATIONS:
case CMD_DISABLE_HOST_AND_CHILD_NOTIFICATIONS:
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
case CMD_ENABLE_HOST_FLAP_DETECTION:
case CMD_DISABLE_HOST_FLAP_DETECTION:
case CMD_ENABLE_HOST_EVENT_HANDLER:
case CMD_DISABLE_HOST_EVENT_HANDLER:
case CMD_START_OBSESSING_OVER_HOST:
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);
break;
/*****************************/
/***** HOSTGROUP COMMANDS ****/
/*****************************/
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_ENABLE_HOSTGROUP_HOST_CHECKS:
case CMD_DISABLE_HOSTGROUP_HOST_CHECKS:
case CMD_ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS:
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
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);
break;
/***************************/
/***** SERVICE COMMANDS ****/
/***************************/
case CMD_ENABLE_SVC_CHECK:
case CMD_DISABLE_SVC_CHECK:
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
case CMD_ENABLE_SVC_NOTIFICATIONS:
case CMD_DISABLE_SVC_NOTIFICATIONS:
case CMD_ENABLE_SVC_FLAP_DETECTION:
case CMD_DISABLE_SVC_FLAP_DETECTION:
case CMD_ENABLE_SVC_EVENT_HANDLER:
case CMD_DISABLE_SVC_EVENT_HANDLER:
case CMD_START_OBSESSING_OVER_SVC:
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);
break;
/********************************/
/***** SERVICEGROUP COMMANDS ****/
/********************************/
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_HOST_CHECKS:
case CMD_DISABLE_SERVICEGROUP_HOST_CHECKS:
case CMD_ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
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);
break;
/**********************************/
/**** CONTACT-RELATED COMMANDS ****/
/**********************************/
case CMD_ENABLE_CONTACT_HOST_NOTIFICATIONS:
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);
break;
/***************************************/
/**** CONTACTGROUP-RELATED COMMANDS ****/
/***************************************/
case CMD_ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS:
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);
break;
/***************************/
/**** UNSORTED COMMANDS ****/
/***************************/
case CMD_ADD_HOST_COMMENT:
case CMD_ADD_SVC_COMMENT:
cmd_add_comment(cmd, entry_time, args);
break;
case CMD_DEL_HOST_COMMENT:
case CMD_DEL_SVC_COMMENT:
cmd_delete_comment(cmd, args);
break;
case CMD_DELAY_HOST_NOTIFICATION:
case CMD_DELAY_SVC_NOTIFICATION:
cmd_delay_notification(cmd, args);
break;
case CMD_SCHEDULE_SVC_CHECK:
case CMD_SCHEDULE_FORCED_SVC_CHECK:
cmd_schedule_check(cmd, args);
break;
case CMD_SCHEDULE_HOST_SVC_CHECKS:
case CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS:
cmd_schedule_check(cmd, args);
break;
case CMD_DEL_ALL_HOST_COMMENTS:
case CMD_DEL_ALL_SVC_COMMENTS:
cmd_delete_all_comments(cmd, args);
break;
case CMD_PROCESS_SERVICE_CHECK_RESULT:
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);
break;
case CMD_ACKNOWLEDGE_HOST_PROBLEM:
case CMD_ACKNOWLEDGE_SVC_PROBLEM:
cmd_acknowledge_problem(cmd, args);
break;
case CMD_REMOVE_HOST_ACKNOWLEDGEMENT:
case CMD_REMOVE_SVC_ACKNOWLEDGEMENT:
cmd_remove_acknowledgement(cmd, args);
break;
case CMD_SCHEDULE_HOST_DOWNTIME:
case CMD_SCHEDULE_SVC_DOWNTIME:
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
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);
break;
case CMD_DEL_HOST_DOWNTIME:
case CMD_DEL_SVC_DOWNTIME:
cmd_delete_downtime(cmd, args);
break;
case CMD_DEL_DOWNTIME_BY_HOST_NAME:
cmd_delete_downtime_by_host_name(cmd, args);
break;
case CMD_DEL_DOWNTIME_BY_HOSTGROUP_NAME:
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:
break;
case CMD_SCHEDULE_HOST_CHECK:
case CMD_SCHEDULE_FORCED_HOST_CHECK:
cmd_schedule_check(cmd, args);
break;
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_EVENT_HANDLER:
case CMD_CHANGE_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_CHECK_COMMAND:
case CMD_CHANGE_SVC_CHECK_COMMAND:
case CMD_CHANGE_HOST_CHECK_TIMEPERIOD:
case CMD_CHANGE_SVC_CHECK_TIMEPERIOD:
case CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD:
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);
break;
case CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL:
case CMD_CHANGE_RETRY_HOST_CHECK_INTERVAL:
case CMD_CHANGE_NORMAL_SVC_CHECK_INTERVAL:
case CMD_CHANGE_RETRY_SVC_CHECK_INTERVAL:
case CMD_CHANGE_MAX_HOST_CHECK_ATTEMPTS:
case CMD_CHANGE_MAX_SVC_CHECK_ATTEMPTS:
case CMD_CHANGE_HOST_MODATTR:
case CMD_CHANGE_SVC_MODATTR:
case CMD_CHANGE_CONTACT_MODATTR:
case CMD_CHANGE_CONTACT_MODHATTR:
case CMD_CHANGE_CONTACT_MODSATTR:
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);
break;
/***********************/
/**** MISC COMMANDS ****/
/***********************/
case CMD_PROCESS_FILE:
cmd_process_external_commands_from_file(cmd, args);
break;
/*************************/
/**** CUSTOM COMMANDS ****/
/*************************/
case CMD_CUSTOM_COMMAND:
/* custom commands aren't handled internally by Nagios, but may be by NEB modules */
break;
default:
return ERROR;
break;
}
return OK;
}
/* processes an external host command */
int process_host_command(int cmd, time_t entry_time, char *args) {
char *host_name = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
char *str = NULL;
char *buf[2] = {NULL, NULL};
int intval = 0;
printf("ARGS: %s\n", args);
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* find the host */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
switch(cmd) {
case CMD_ENABLE_HOST_NOTIFICATIONS:
enable_host_notifications(temp_host);
break;
case CMD_DISABLE_HOST_NOTIFICATIONS:
disable_host_notifications(temp_host);
break;
case CMD_ENABLE_HOST_AND_CHILD_NOTIFICATIONS:
enable_and_propagate_notifications(temp_host, 0, TRUE, TRUE, FALSE);
break;
case CMD_DISABLE_HOST_AND_CHILD_NOTIFICATIONS:
disable_and_propagate_notifications(temp_host, 0, TRUE, TRUE, FALSE);
break;
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
enable_and_propagate_notifications(temp_host, 0, FALSE, TRUE, TRUE);
break;
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
disable_and_propagate_notifications(temp_host, 0, FALSE, TRUE, TRUE);
break;
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
if(cmd == CMD_ENABLE_HOST_SVC_NOTIFICATIONS)
enable_service_notifications(temp_service);
else
disable_service_notifications(temp_service);
}
break;
case CMD_ENABLE_HOST_SVC_CHECKS:
case CMD_DISABLE_HOST_SVC_CHECKS:
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
if(cmd == CMD_ENABLE_HOST_SVC_CHECKS)
enable_service_checks(temp_service);
else
disable_service_checks(temp_service);
}
break;
case CMD_ENABLE_HOST_CHECK:
enable_host_checks(temp_host);
break;
case CMD_DISABLE_HOST_CHECK:
disable_host_checks(temp_host);
break;
case CMD_ENABLE_HOST_EVENT_HANDLER:
enable_host_event_handler(temp_host);
break;
case CMD_DISABLE_HOST_EVENT_HANDLER:
disable_host_event_handler(temp_host);
break;
case CMD_ENABLE_HOST_FLAP_DETECTION:
enable_host_flap_detection(temp_host);
break;
case CMD_DISABLE_HOST_FLAP_DETECTION:
disable_host_flap_detection(temp_host);
break;
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
enable_passive_host_checks(temp_host);
break;
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
disable_passive_host_checks(temp_host);
break;
case CMD_START_OBSESSING_OVER_HOST:
start_obsessing_over_host(temp_host);
break;
case CMD_STOP_OBSESSING_OVER_HOST:
stop_obsessing_over_host(temp_host);
break;
case CMD_SET_HOST_NOTIFICATION_NUMBER:
if((str = my_strtok(NULL, ";"))) {
intval = atoi(str);
set_host_notification_number(temp_host, intval);
}
break;
case CMD_SEND_CUSTOM_HOST_NOTIFICATION:
if((str = my_strtok(NULL, ";")))
intval = atoi(str);
str = my_strtok(NULL, ";");
if(str)
buf[0] = strdup(str);
str = my_strtok(NULL, ";");
if(str)
buf[1] = strdup(str);
if(buf[0] && buf[1])
host_notification(temp_host, NOTIFICATION_CUSTOM, buf[0], buf[1], intval);
break;
default:
break;
}
return OK;
}
/* processes an external hostgroup command */
int process_hostgroup_command(int cmd, time_t entry_time, char *args) {
char *hostgroup_name = NULL;
hostgroup *temp_hostgroup = NULL;
hostsmember *temp_member = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
/* get the hostgroup name */
if((hostgroup_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* find the hostgroup */
if((temp_hostgroup = find_hostgroup(hostgroup_name)) == NULL)
return ERROR;
/* loop through all hosts in the hostgroup */
for(temp_member = temp_hostgroup->members; temp_member != NULL; temp_member = temp_member->next) {
if((temp_host = (host *)temp_member->host_ptr) == NULL)
continue;
switch(cmd) {
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
enable_host_notifications(temp_host);
break;
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
disable_host_notifications(temp_host);
break;
case CMD_ENABLE_HOSTGROUP_HOST_CHECKS:
enable_host_checks(temp_host);
break;
case CMD_DISABLE_HOSTGROUP_HOST_CHECKS:
disable_host_checks(temp_host);
break;
case CMD_ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS:
enable_passive_host_checks(temp_host);
break;
case CMD_DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS:
disable_passive_host_checks(temp_host);
break;
default:
/* loop through all services on the host */
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
switch(cmd) {
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
enable_service_notifications(temp_service);
break;
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
disable_service_notifications(temp_service);
break;
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
enable_service_checks(temp_service);
break;
case CMD_DISABLE_HOSTGROUP_SVC_CHECKS:
disable_service_checks(temp_service);
break;
case CMD_ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS:
enable_passive_service_checks(temp_service);
break;
case CMD_DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS:
disable_passive_service_checks(temp_service);
break;
default:
break;
}
}
break;
}
}
return OK;
}
/* processes an external service command */
int process_service_command(int cmd, time_t entry_time, char *args) {
char *host_name = NULL;
char *svc_description = NULL;
service *temp_service = NULL;
char *str = NULL;
char *buf[2] = {NULL, NULL};
int intval = 0;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* get the service description */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* find the service */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
switch(cmd) {
case CMD_ENABLE_SVC_NOTIFICATIONS:
enable_service_notifications(temp_service);
break;
case CMD_DISABLE_SVC_NOTIFICATIONS:
disable_service_notifications(temp_service);
break;
case CMD_ENABLE_SVC_CHECK:
enable_service_checks(temp_service);
break;
case CMD_DISABLE_SVC_CHECK:
disable_service_checks(temp_service);
break;
case CMD_ENABLE_SVC_EVENT_HANDLER:
enable_service_event_handler(temp_service);
break;
case CMD_DISABLE_SVC_EVENT_HANDLER:
disable_service_event_handler(temp_service);
break;
case CMD_ENABLE_SVC_FLAP_DETECTION:
enable_service_flap_detection(temp_service);
break;
case CMD_DISABLE_SVC_FLAP_DETECTION:
disable_service_flap_detection(temp_service);
break;
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
enable_passive_service_checks(temp_service);
break;
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
disable_passive_service_checks(temp_service);
break;
case CMD_START_OBSESSING_OVER_SVC:
start_obsessing_over_service(temp_service);
break;
case CMD_STOP_OBSESSING_OVER_SVC:
stop_obsessing_over_service(temp_service);
break;
case CMD_SET_SVC_NOTIFICATION_NUMBER:
if((str = my_strtok(NULL, ";"))) {
intval = atoi(str);
set_service_notification_number(temp_service, intval);
}
break;
case CMD_SEND_CUSTOM_SVC_NOTIFICATION:
if((str = my_strtok(NULL, ";")))
intval = atoi(str);
str = my_strtok(NULL, ";");
if(str)
buf[0] = strdup(str);
str = my_strtok(NULL, ";");
if(str)
buf[1] = strdup(str);
if(buf[0] && buf[1])
service_notification(temp_service, NOTIFICATION_CUSTOM, buf[0], buf[1], intval);
break;
default:
break;
}
return OK;
}
/* processes an external servicegroup command */
int process_servicegroup_command(int cmd, time_t entry_time, char *args) {
char *servicegroup_name = NULL;
servicegroup *temp_servicegroup = NULL;
servicesmember *temp_member = NULL;
host *temp_host = NULL;
host *last_host = NULL;
service *temp_service = NULL;
/* get the servicegroup name */
if((servicegroup_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* find the servicegroup */
if((temp_servicegroup = find_servicegroup(servicegroup_name)) == NULL)
return ERROR;
switch(cmd) {
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS:
/* loop through all servicegroup members */
for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) {
temp_service = find_service(temp_member->host_name, temp_member->service_description);
if(temp_service == NULL)
continue;
switch(cmd) {
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
enable_service_notifications(temp_service);
break;
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
disable_service_notifications(temp_service);
break;
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
enable_service_checks(temp_service);
break;
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
disable_service_checks(temp_service);
break;
case CMD_ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS:
enable_passive_service_checks(temp_service);
break;
case CMD_DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS:
disable_passive_service_checks(temp_service);
break;
default:
break;
}
}
break;
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_HOST_CHECKS:
case CMD_DISABLE_SERVICEGROUP_HOST_CHECKS:
case CMD_ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
/* loop through all hosts that have services belonging to the servicegroup */
last_host = NULL;
for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) {
if((temp_host = find_host(temp_member->host_name)) == NULL)
continue;
if(temp_host == last_host)
continue;
switch(cmd) {
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
enable_host_notifications(temp_host);
break;
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
disable_host_notifications(temp_host);
break;
case CMD_ENABLE_SERVICEGROUP_HOST_CHECKS:
enable_host_checks(temp_host);
break;
case CMD_DISABLE_SERVICEGROUP_HOST_CHECKS:
disable_host_checks(temp_host);
break;
case CMD_ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
enable_passive_host_checks(temp_host);
break;
case CMD_DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
disable_passive_host_checks(temp_host);
break;
default:
break;
}
last_host = temp_host;
}
break;
default:
break;
}
return OK;
}
/* processes an external contact command */
int process_contact_command(int cmd, time_t entry_time, char *args) {
char *contact_name = NULL;
contact *temp_contact = NULL;
/* get the contact name */
if((contact_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* find the contact */
if((temp_contact = find_contact(contact_name)) == NULL)
return ERROR;
switch(cmd) {
case CMD_ENABLE_CONTACT_HOST_NOTIFICATIONS:
enable_contact_host_notifications(temp_contact);
break;
case CMD_DISABLE_CONTACT_HOST_NOTIFICATIONS:
disable_contact_host_notifications(temp_contact);
break;
case CMD_ENABLE_CONTACT_SVC_NOTIFICATIONS:
enable_contact_service_notifications(temp_contact);
break;
case CMD_DISABLE_CONTACT_SVC_NOTIFICATIONS:
disable_contact_service_notifications(temp_contact);
break;
default:
break;
}
return OK;
}
/* processes an external contactgroup command */
int process_contactgroup_command(int cmd, time_t entry_time, char *args) {
char *contactgroup_name = NULL;
contactgroup *temp_contactgroup = NULL;
contactsmember *temp_member = NULL;
contact *temp_contact = NULL;
/* get the contactgroup name */
if((contactgroup_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* find the contactgroup */
if((temp_contactgroup = find_contactgroup(contactgroup_name)) == NULL)
return ERROR;
switch(cmd) {
case CMD_ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS:
/* loop through all contactgroup members */
for(temp_member = temp_contactgroup->members; temp_member != NULL; temp_member = temp_member->next) {
if((temp_contact = temp_member->contact_ptr) == NULL)
continue;
switch(cmd) {
case CMD_ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS:
enable_contact_host_notifications(temp_contact);
break;
case CMD_DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS:
disable_contact_host_notifications(temp_contact);
break;
case CMD_ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS:
enable_contact_service_notifications(temp_contact);
break;
case CMD_DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS:
disable_contact_service_notifications(temp_contact);
break;
default:
break;
}
}
break;
default:
break;
}
return OK;
}
/******************************************************************/
/*************** EXTERNAL COMMAND IMPLEMENTATIONS ****************/
/******************************************************************/
/* adds a host or service comment to the status log */
int cmd_add_comment(int cmd, time_t entry_time, char *args) {
char *temp_ptr = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
char *host_name = NULL;
char *svc_description = NULL;
char *user = NULL;
char *comment_data = NULL;
int persistent = 0;
int result = 0;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* if we're adding a service comment... */
if(cmd == CMD_ADD_SVC_COMMENT) {
/* get the service description */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
}
/* else verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* get the persistent flag */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
persistent = atoi(temp_ptr);
if(persistent > 1)
persistent = 1;
else if(persistent < 0)
persistent = 0;
/* get the name of the user who entered the comment */
if((user = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* get the comment */
if((comment_data = my_strtok(NULL, "\n")) == NULL)
return ERROR;
/* add the comment */
result = add_new_comment((cmd == CMD_ADD_HOST_COMMENT) ? HOST_COMMENT : SERVICE_COMMENT, USER_COMMENT, host_name, svc_description, entry_time, user, comment_data, persistent, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
if(result < 0)
return ERROR;
return OK;
}
/* removes a host or service comment from the status log */
int cmd_delete_comment(int cmd, char *args) {
unsigned long comment_id = 0L;
/* get the comment id we should delete */
if((comment_id = strtoul(args, NULL, 10)) == 0)
return ERROR;
/* delete the specified comment */
if(cmd == CMD_DEL_HOST_COMMENT)
delete_host_comment(comment_id);
else
delete_service_comment(comment_id);
return OK;
}
/* removes all comments associated with a host or service from the status log */
int cmd_delete_all_comments(int cmd, char *args) {
service *temp_service = NULL;
host *temp_host = NULL;
char *host_name = NULL;
char *svc_description = NULL;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* if we're deleting service comments... */
if(cmd == CMD_DEL_ALL_SVC_COMMENTS) {
/* get the service description */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
}
/* else verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* delete comments */
delete_all_comments((cmd == CMD_DEL_ALL_HOST_COMMENTS) ? HOST_COMMENT : SERVICE_COMMENT, host_name, svc_description);
return OK;
}
/* delays a host or service notification for given number of minutes */
int cmd_delay_notification(int cmd, char *args) {
char *temp_ptr = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
char *host_name = NULL;
char *svc_description = NULL;
time_t delay_time = 0L;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* if this is a service notification delay... */
if(cmd == CMD_DELAY_SVC_NOTIFICATION) {
/* get the service description */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
}
/* else verify that the host is valid */
else {
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
}
/* get the time that we should delay until... */
if((temp_ptr = my_strtok(NULL, "\n")) == NULL)
return ERROR;
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
temp_service->next_notification = delay_time;
return OK;
}
/* schedules a host check at a particular time */
int cmd_schedule_check(int cmd, char *args) {
char *temp_ptr = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
char *host_name = NULL;
char *svc_description = NULL;
time_t delay_time = 0L;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
if(cmd == CMD_SCHEDULE_HOST_CHECK || cmd == CMD_SCHEDULE_FORCED_HOST_CHECK || cmd == CMD_SCHEDULE_HOST_SVC_CHECKS || cmd == CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS) {
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
}
else {
/* get the service description */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
}
/* get the next check time */
if((temp_ptr = my_strtok(NULL, "\n")) == NULL)
return ERROR;
delay_time = strtoul(temp_ptr, NULL, 10);
/* schedule the host check */
if(cmd == CMD_SCHEDULE_HOST_CHECK || cmd == CMD_SCHEDULE_FORCED_HOST_CHECK)
schedule_host_check(temp_host, delay_time, (cmd == CMD_SCHEDULE_FORCED_HOST_CHECK) ? CHECK_OPTION_FORCE_EXECUTION : CHECK_OPTION_NONE);
/* schedule service checks */
else if(cmd == CMD_SCHEDULE_HOST_SVC_CHECKS || cmd == CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS) {
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
schedule_service_check(temp_service, delay_time, (cmd == CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS) ? CHECK_OPTION_FORCE_EXECUTION : CHECK_OPTION_NONE);
}
}
else
schedule_service_check(temp_service, delay_time, (cmd == CMD_SCHEDULE_FORCED_SVC_CHECK) ? CHECK_OPTION_FORCE_EXECUTION : CHECK_OPTION_NONE);
return OK;
}
/* schedules all service checks on a host for a particular time */
int cmd_schedule_host_service_checks(int cmd, char *args, int force) {
char *temp_ptr = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
host *temp_host = NULL;
char *host_name = NULL;
time_t delay_time = 0L;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* get the next check time */
if((temp_ptr = my_strtok(NULL, "\n")) == NULL)
return ERROR;
delay_time = strtoul(temp_ptr, NULL, 10);
/* reschedule all services on the specified host */
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
schedule_service_check(temp_service, delay_time, (force == TRUE) ? CHECK_OPTION_FORCE_EXECUTION : CHECK_OPTION_NONE);
}
return OK;
}
/* schedules a program shutdown or restart */
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)
scheduled_time = 0L;
else
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);
return result;
}
/* processes results of an external service check */
int cmd_process_service_check_result(int cmd, time_t check_time, char *args) {
char *temp_ptr = NULL;
char *host_name = NULL;
char *svc_description = NULL;
int return_code = 0;
char *output = NULL;
int result = 0;
/* get the host name */
if((temp_ptr = my_strtok(args, ";")) == NULL)
return ERROR;
host_name = (char *)strdup(temp_ptr);
/* get the service description */
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(host_name);
return ERROR;
}
svc_description = (char *)strdup(temp_ptr);
/* get the service check return code */
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(host_name);
my_free(svc_description);
return ERROR;
}
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);
/* submit the passive check result */
result = process_passive_service_check(check_time, host_name, svc_description, return_code, output);
/* free memory */
my_free(host_name);
my_free(svc_description);
my_free(output);
return result;
}
/* 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;
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)
return ERROR;
/* make sure we have all required data */
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;
}
}
}
/* we couldn't find the host */
if(real_host_name == 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) {
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)
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 = 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;
/* 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;
/* 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;
}
/* process passive host check result */
int cmd_process_host_check_result(int cmd, time_t check_time, char *args) {
char *temp_ptr = NULL;
char *host_name = NULL;
int return_code = 0;
char *output = NULL;
int result = 0;
/* get the host name */
if((temp_ptr = my_strtok(args, ";")) == NULL)
return ERROR;
host_name = (char *)strdup(temp_ptr);
/* get the host check return code */
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(host_name);
return ERROR;
}
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);
/* submit the check result */
result = process_passive_host_check(check_time, host_name, return_code, output);
/* free memory */
my_free(host_name);
my_free(output);
return result;
}
/* 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;
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)
return ERROR;
/* make sure we have all required data */
if(host_name == NULL || output == NULL)
return ERROR;
/* make sure we have a reasonable return code */
if(return_code < 0 || return_code > 2)
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;
}
}
}
/* we couldn't find the host */
if(temp_host == NULL) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Passive check result was received for host '%s', but the host could not be found!\n", host_name);
return ERROR;
}
/* skip this is we aren't accepting passive checks for this host */
if(temp_host->accept_passive_host_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;
/* 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;
/* 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;
}
/* acknowledges a host or service problem */
int cmd_acknowledge_problem(int cmd, char *args) {
service *temp_service = NULL;
host *temp_host = NULL;
char *host_name = NULL;
char *svc_description = NULL;
char *ack_author = NULL;
char *ack_data = NULL;
char *temp_ptr = NULL;
int type = ACKNOWLEDGEMENT_NORMAL;
int notify = TRUE;
int persistent = TRUE;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* this is a service acknowledgement */
if(cmd == CMD_ACKNOWLEDGE_SVC_PROBLEM) {
/* get the service name */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(temp_host->name, svc_description)) == NULL)
return ERROR;
}
/* get the type */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
type = atoi(temp_ptr);
/* get the notification option */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
notify = (atoi(temp_ptr) > 0) ? TRUE : FALSE;
/* get the persistent option */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
persistent = (atoi(temp_ptr) > 0) ? TRUE : FALSE;
/* get the acknowledgement author */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
ack_author = (char *)strdup(temp_ptr);
/* get the acknowledgement data */
if((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
my_free(ack_author);
return ERROR;
}
ack_data = (char *)strdup(temp_ptr);
/* acknowledge the host problem */
if(cmd == CMD_ACKNOWLEDGE_HOST_PROBLEM)
acknowledge_host_problem(temp_host, ack_author, ack_data, type, notify, persistent);
/* acknowledge the service problem */
else
acknowledge_service_problem(temp_service, ack_author, ack_data, type, notify, persistent);
/* free memory */
my_free(ack_author);
my_free(ack_data);
return OK;
}
/* removes a host or service acknowledgement */
int cmd_remove_acknowledgement(int cmd, char *args) {
service *temp_service = NULL;
host *temp_host = NULL;
char *host_name = NULL;
char *svc_description = NULL;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* we are removing a service acknowledgement */
if(cmd == CMD_REMOVE_SVC_ACKNOWLEDGEMENT) {
/* get the service name */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(temp_host->name, svc_description)) == NULL)
return ERROR;
}
/* acknowledge the host problem */
if(cmd == CMD_REMOVE_HOST_ACKNOWLEDGEMENT)
remove_host_acknowledgement(temp_host);
/* acknowledge the service problem */
else
remove_service_acknowledgement(temp_service);
return OK;
}
/* schedules downtime for a specific host or service */
int cmd_schedule_downtime(int cmd, time_t entry_time, char *args) {
servicesmember *temp_servicesmember = NULL;
service *temp_service = NULL;
host *temp_host = NULL;
host *last_host = NULL;
hostgroup *temp_hostgroup = NULL;
hostsmember *temp_hgmember = NULL;
servicegroup *temp_servicegroup = NULL;
servicesmember *temp_sgmember = NULL;
char *host_name = NULL;
char *hostgroup_name = NULL;
char *servicegroup_name = NULL;
char *svc_description = NULL;
char *temp_ptr = NULL;
time_t start_time = 0L;
time_t end_time = 0L;
int fixed = 0;
unsigned long triggered_by = 0L;
unsigned long duration = 0L;
char *author = NULL;
char *comment_data = NULL;
unsigned long downtime_id = 0L;
if(cmd == CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME || cmd == CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME) {
/* get the hostgroup name */
if((hostgroup_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the hostgroup is valid */
if((temp_hostgroup = find_hostgroup(hostgroup_name)) == NULL)
return ERROR;
}
else if(cmd == CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME || cmd == CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME) {
/* get the servicegroup name */
if((servicegroup_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the servicegroup is valid */
if((temp_servicegroup = find_servicegroup(servicegroup_name)) == NULL)
return ERROR;
}
else {
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* this is a service downtime */
if(cmd == CMD_SCHEDULE_SVC_DOWNTIME) {
/* get the service name */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(temp_host->name, svc_description)) == NULL)
return ERROR;
}
}
/* get the start time */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
start_time = (time_t)strtoul(temp_ptr, NULL, 10);
/* get the end time */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
end_time = (time_t)strtoul(temp_ptr, NULL, 10);
/* get the fixed flag */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
fixed = atoi(temp_ptr);
/* get the trigger id */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
triggered_by = strtoul(temp_ptr, NULL, 10);
/* get the duration */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
duration = strtoul(temp_ptr, NULL, 10);
/* get the author */
if((author = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* get the comment */
if((comment_data = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* check if flexible downtime demanded and duration set
to non-zero.
according to the documentation, a flexible downtime is
started between start and end time and will last for
"duration" seconds. strtoul converts a NULL value to 0
so if set to 0, bail out as a duration>0 is needed. */
if(fixed == 0 && duration == 0)
return ERROR;
/* duration should be auto-calculated, not user-specified */
if(fixed > 0)
duration = (unsigned long)(end_time - start_time);
/* schedule downtime */
switch(cmd) {
case CMD_SCHEDULE_HOST_DOWNTIME:
schedule_downtime(HOST_DOWNTIME, host_name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
break;
case CMD_SCHEDULE_SVC_DOWNTIME:
schedule_downtime(SERVICE_DOWNTIME, host_name, svc_description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
break;
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
schedule_downtime(SERVICE_DOWNTIME, host_name, temp_service->description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
}
break;
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
for(temp_hgmember = temp_hostgroup->members; temp_hgmember != NULL; temp_hgmember = temp_hgmember->next)
schedule_downtime(HOST_DOWNTIME, temp_hgmember->host_name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
break;
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
for(temp_hgmember = temp_hostgroup->members; temp_hgmember != NULL; temp_hgmember = temp_hgmember->next) {
if((temp_host = temp_hgmember->host_ptr) == NULL)
continue;
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
schedule_downtime(SERVICE_DOWNTIME, temp_service->host_name, temp_service->description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
}
}
break;
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
last_host = NULL;
for(temp_sgmember = temp_servicegroup->members; temp_sgmember != NULL; temp_sgmember = temp_sgmember->next) {
temp_host = find_host(temp_sgmember->host_name);
if(temp_host == NULL)
continue;
if(last_host == temp_host)
continue;
schedule_downtime(HOST_DOWNTIME, temp_sgmember->host_name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
last_host = temp_host;
}
break;
case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME:
for(temp_sgmember = temp_servicegroup->members; temp_sgmember != NULL; temp_sgmember = temp_sgmember->next)
schedule_downtime(SERVICE_DOWNTIME, temp_sgmember->host_name, temp_sgmember->service_description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
break;
case CMD_SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME:
/* schedule downtime for "parent" host */
schedule_downtime(HOST_DOWNTIME, host_name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
/* schedule (non-triggered) downtime for all child hosts */
schedule_and_propagate_downtime(temp_host, entry_time, author, comment_data, start_time, end_time, fixed, 0, duration);
break;
case CMD_SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME:
/* schedule downtime for "parent" host */
schedule_downtime(HOST_DOWNTIME, host_name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
/* schedule triggered downtime for all child hosts */
schedule_and_propagate_downtime(temp_host, entry_time, author, comment_data, start_time, end_time, fixed, downtime_id, duration);
break;
default:
break;
}
return OK;
}
/* deletes scheduled host or service downtime */
int cmd_delete_downtime(int cmd, char *args) {
unsigned long downtime_id = 0L;
char *temp_ptr = NULL;
/* get the id of the downtime to delete */
if((temp_ptr = my_strtok(args, "\n")) == NULL)
return ERROR;
downtime_id = strtoul(temp_ptr, NULL, 10);
if(cmd == CMD_DEL_HOST_DOWNTIME)
unschedule_downtime(HOST_DOWNTIME, downtime_id);
else
unschedule_downtime(SERVICE_DOWNTIME, downtime_id);
return OK;
}
/* 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;
char *end_ptr = NULL;
char *hostname = NULL;
char *service_description = NULL;
char *downtime_comment = NULL;
time_t downtime_start_time = 0L;
int deleted = 0;
/* get the host name of the downtime to delete */
temp_ptr = my_strtok(args, ";");
if(temp_ptr == NULL)
return ERROR;
hostname = temp_ptr;
/* get the optional service name */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
service_description = temp_ptr;
/* get the optional start time */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
downtime_start_time = strtoul(temp_ptr, &end_ptr, 10);
/* get the optional comment */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
downtime_comment = temp_ptr;
}
}
}
deleted = delete_downtime_by_hostname_service_description_start_time_comment(hostname, service_description, downtime_start_time, downtime_comment);
if(deleted == 0)
return ERROR;
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;
host *temp_host = NULL;
hostgroup *temp_hostgroup = NULL;
hostsmember *temp_member = NULL;
char *service_description = NULL;
char *downtime_comment = NULL;
char *host_name = NULL;
time_t downtime_start_time = 0L;
int deleted = 0;
/* get the host group name of the downtime to delete */
temp_ptr = my_strtok(args, ";");
if(temp_ptr == NULL)
return ERROR;
temp_hostgroup = find_hostgroup(temp_ptr);
if(temp_hostgroup == NULL)
return ERROR;
/* get the optional host name */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
host_name = temp_ptr;
/* get the optional service name */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
service_description = temp_ptr;
/* get the optional start time */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
downtime_start_time = strtoul(temp_ptr, &end_ptr, 10);
/* get the optional comment */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
downtime_comment = temp_ptr;
}
}
}
/* get the optional service name */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
service_description = temp_ptr;
/* get the optional start time */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
downtime_start_time = strtoul(temp_ptr, &end_ptr, 10);
/* get the optional comment */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
downtime_comment = temp_ptr;
}
}
}
}
for(temp_member = temp_hostgroup->members; temp_member != NULL; temp_member = temp_member->next) {
if((temp_host = (host *)temp_member->host_ptr) == NULL)
continue;
if(host_name != NULL && strcmp(temp_host->name, host_name) != 0)
continue;
deleted = +delete_downtime_by_hostname_service_description_start_time_comment(temp_host->name, service_description, downtime_start_time, downtime_comment);
}
if(deleted == 0)
return ERROR;
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;
char *temp_ptr = NULL;
char *end_ptr = NULL;
int deleted = 0;
/* Get start time if set */
temp_ptr = my_strtok(args, ";");
if(temp_ptr != NULL) {
/* This will be set to 0 if no start_time is entered or data is bad */
downtime_start_time = strtoul(temp_ptr, &end_ptr, 10);
}
/* Get comment - not sure if this should be also tokenised by ; */
temp_ptr = my_strtok(NULL, "\n");
if(temp_ptr != NULL && *temp_ptr != '\0') {
downtime_comment = temp_ptr;
}
/* No args should give an error */
if(downtime_start_time == 0 && downtime_comment == NULL)
return ERROR;
deleted = delete_downtime_by_hostname_service_description_start_time_comment(NULL, NULL, downtime_start_time, downtime_comment);
if(deleted == 0)
return ERROR;
return OK;
}
/* changes a host or service (integer) variable */
int cmd_change_object_int_var(int cmd, char *args) {
service *temp_service = NULL;
host *temp_host = NULL;
contact *temp_contact = NULL;
char *host_name = NULL;
char *svc_description = NULL;
char *contact_name = NULL;
char *temp_ptr = NULL;
int intval = 0;
double dval = 0.0;
double old_dval = 0.0;
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
unsigned long attr = MODATTR_NONE;
unsigned long hattr = MODATTR_NONE;
unsigned long sattr = MODATTR_NONE;
switch(cmd) {
case CMD_CHANGE_NORMAL_SVC_CHECK_INTERVAL:
case CMD_CHANGE_RETRY_SVC_CHECK_INTERVAL:
case CMD_CHANGE_MAX_SVC_CHECK_ATTEMPTS:
case CMD_CHANGE_SVC_MODATTR:
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* get the service name */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
break;
case CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL:
case CMD_CHANGE_RETRY_HOST_CHECK_INTERVAL:
case CMD_CHANGE_MAX_HOST_CHECK_ATTEMPTS:
case CMD_CHANGE_HOST_MODATTR:
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
break;
case CMD_CHANGE_CONTACT_MODATTR:
case CMD_CHANGE_CONTACT_MODHATTR:
case CMD_CHANGE_CONTACT_MODSATTR:
/* get the contact name */
if((contact_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the contact is valid */
if((temp_contact = find_contact(contact_name)) == NULL)
return ERROR;
break;
default:
/* unknown command */
return ERROR;
break;
}
/* get the value */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
intval = (int)strtol(temp_ptr, NULL, 0);
if(intval < 0 || (intval == 0 && errno == EINVAL))
return ERROR;
dval = (int)strtod(temp_ptr, NULL);
switch(cmd) {
case CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL:
/* save the old check interval */
old_dval = temp_host->check_interval;
/* modify the check interval */
temp_host->check_interval = dval;
attr = MODATTR_NORMAL_CHECK_INTERVAL;
/* schedule a host check if previous interval was 0 (checks were not regularly scheduled) */
if(old_dval == 0 && temp_host->checks_enabled == TRUE) {
/* set the host check flag */
temp_host->should_be_scheduled = TRUE;
/* schedule a check for right now (or as soon as possible) */
time(&preferred_time);
if(check_time_against_period(preferred_time, temp_host->check_period_ptr) == ERROR) {
get_next_valid_time(preferred_time, &next_valid_time, temp_host->check_period_ptr);
temp_host->next_check = next_valid_time;
}
else
temp_host->next_check = preferred_time;
/* schedule a check if we should */
if(temp_host->should_be_scheduled == TRUE)
schedule_host_check(temp_host, temp_host->next_check, CHECK_OPTION_NONE);
}
break;
case CMD_CHANGE_RETRY_HOST_CHECK_INTERVAL:
temp_host->retry_interval = dval;
attr = MODATTR_RETRY_CHECK_INTERVAL;
break;
case CMD_CHANGE_MAX_HOST_CHECK_ATTEMPTS:
temp_host->max_attempts = intval;
attr = MODATTR_MAX_CHECK_ATTEMPTS;
/* adjust current attempt number if in a hard state */
if(temp_host->state_type == HARD_STATE && temp_host->current_state != HOST_UP && temp_host->current_attempt > 1)
temp_host->current_attempt = temp_host->max_attempts;
break;
case CMD_CHANGE_NORMAL_SVC_CHECK_INTERVAL:
/* save the old check interval */
old_dval = temp_service->check_interval;
/* modify the check interval */
temp_service->check_interval = dval;
attr = MODATTR_NORMAL_CHECK_INTERVAL;
/* schedule a service check if previous interval was 0 (checks were not regularly scheduled) */
if(old_dval == 0 && temp_service->checks_enabled == TRUE && temp_service->check_interval != 0) {
/* set the service check flag */
temp_service->should_be_scheduled = TRUE;
/* schedule a check for right now (or as soon as possible) */
time(&preferred_time);
if(check_time_against_period(preferred_time, temp_service->check_period_ptr) == ERROR) {
get_next_valid_time(preferred_time, &next_valid_time, temp_service->check_period_ptr);
temp_service->next_check = next_valid_time;
}
else
temp_service->next_check = preferred_time;
/* schedule a check if we should */
if(temp_service->should_be_scheduled == TRUE)
schedule_service_check(temp_service, temp_service->next_check, CHECK_OPTION_NONE);
}
break;
case CMD_CHANGE_RETRY_SVC_CHECK_INTERVAL:
temp_service->retry_interval = dval;
attr = MODATTR_RETRY_CHECK_INTERVAL;
break;
case CMD_CHANGE_MAX_SVC_CHECK_ATTEMPTS:
temp_service->max_attempts = intval;
attr = MODATTR_MAX_CHECK_ATTEMPTS;
/* adjust current attempt number if in a hard state */
if(temp_service->state_type == HARD_STATE && temp_service->current_state != STATE_OK && temp_service->current_attempt > 1)
temp_service->current_attempt = temp_service->max_attempts;
break;
case CMD_CHANGE_HOST_MODATTR:
case CMD_CHANGE_SVC_MODATTR:
case CMD_CHANGE_CONTACT_MODATTR:
attr = intval;
break;
case CMD_CHANGE_CONTACT_MODHATTR:
hattr = intval;
break;
case CMD_CHANGE_CONTACT_MODSATTR:
sattr = intval;
break;
default:
break;
}
/* send data to event broker and update status file */
switch(cmd) {
case CMD_CHANGE_RETRY_SVC_CHECK_INTERVAL:
case CMD_CHANGE_NORMAL_SVC_CHECK_INTERVAL:
case CMD_CHANGE_MAX_SVC_CHECK_ATTEMPTS:
case CMD_CHANGE_SVC_MODATTR:
/* set the modified service attribute */
if(cmd == CMD_CHANGE_SVC_MODATTR)
temp_service->modified_attributes = attr;
else
temp_service->modified_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_service, cmd, attr, temp_service->modified_attributes, NULL);
#endif
/* update the status log with the service info */
update_service_status(temp_service, FALSE);
break;
case CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL:
case CMD_CHANGE_RETRY_HOST_CHECK_INTERVAL:
case CMD_CHANGE_MAX_HOST_CHECK_ATTEMPTS:
case CMD_CHANGE_HOST_MODATTR:
/* set the modified host attribute */
if(cmd == CMD_CHANGE_HOST_MODATTR)
temp_host->modified_attributes = attr;
else
temp_host->modified_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_host, cmd, attr, temp_host->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(temp_host, FALSE);
break;
case CMD_CHANGE_CONTACT_MODATTR:
case CMD_CHANGE_CONTACT_MODHATTR:
case CMD_CHANGE_CONTACT_MODSATTR:
/* set the modified attribute */
switch(cmd) {
case CMD_CHANGE_CONTACT_MODATTR:
temp_contact->modified_attributes = attr;
break;
case CMD_CHANGE_CONTACT_MODHATTR:
temp_contact->modified_host_attributes = hattr;
break;
case CMD_CHANGE_CONTACT_MODSATTR:
temp_contact->modified_service_attributes = sattr;
break;
default:
break;
}
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_contact, cmd, attr, temp_contact->modified_attributes, hattr, temp_contact->modified_host_attributes, sattr, temp_contact->modified_service_attributes, NULL);
#endif
/* update the status log with the contact info */
update_contact_status(temp_contact, FALSE);
break;
default:
break;
}
return OK;
}
/* changes a host or service (char) variable */
int cmd_change_object_char_var(int cmd, char *args) {
service *temp_service = NULL;
host *temp_host = NULL;
contact *temp_contact = NULL;
timeperiod *temp_timeperiod = NULL;
command *temp_command = NULL;
char *host_name = NULL;
char *svc_description = NULL;
char *contact_name = NULL;
char *charval = NULL;
char *temp_ptr = NULL;
char *temp_ptr2 = NULL;
unsigned long attr = MODATTR_NONE;
unsigned long hattr = MODATTR_NONE;
unsigned long sattr = MODATTR_NONE;
/* SECURITY PATCH - disable these for the time being */
switch(cmd) {
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_EVENT_HANDLER:
case CMD_CHANGE_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_CHECK_COMMAND:
case CMD_CHANGE_SVC_CHECK_COMMAND:
return ERROR;
}
/* get the command arguments */
switch(cmd) {
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
if((charval = my_strtok(args, "\n")) == NULL)
return ERROR;
break;
case CMD_CHANGE_HOST_EVENT_HANDLER:
case CMD_CHANGE_HOST_CHECK_COMMAND:
case CMD_CHANGE_HOST_CHECK_TIMEPERIOD:
case CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD:
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
if((charval = my_strtok(NULL, "\n")) == NULL)
return ERROR;
break;
case CMD_CHANGE_SVC_EVENT_HANDLER:
case CMD_CHANGE_SVC_CHECK_COMMAND:
case CMD_CHANGE_SVC_CHECK_TIMEPERIOD:
case CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD:
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* get the service name */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
if((charval = my_strtok(NULL, "\n")) == NULL)
return ERROR;
break;
case CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD:
/* get the contact name */
if((contact_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the contact is valid */
if((temp_contact = find_contact(contact_name)) == NULL)
return ERROR;
if((charval = my_strtok(NULL, "\n")) == NULL)
return ERROR;
break;
default:
/* invalid command */
return ERROR;
break;
}
if((temp_ptr = (char *)strdup(charval)) == NULL)
return ERROR;
/* do some validation */
switch(cmd) {
case CMD_CHANGE_HOST_CHECK_TIMEPERIOD:
case CMD_CHANGE_SVC_CHECK_TIMEPERIOD:
case CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD:
/* make sure the timeperiod is valid */
if((temp_timeperiod = find_timeperiod(temp_ptr)) == NULL) {
my_free(temp_ptr);
return ERROR;
}
break;
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_EVENT_HANDLER:
case CMD_CHANGE_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_CHECK_COMMAND:
case CMD_CHANGE_SVC_CHECK_COMMAND:
/* make sure the command exists */
temp_ptr2 = my_strtok(temp_ptr, "!");
if((temp_command = find_command(temp_ptr2)) == NULL) {
my_free(temp_ptr);
return ERROR;
}
my_free(temp_ptr);
if((temp_ptr = (char *)strdup(charval)) == NULL)
return ERROR;
break;
default:
break;
}
/* update the variable */
switch(cmd) {
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
my_free(global_host_event_handler);
global_host_event_handler = temp_ptr;
global_host_event_handler_ptr = temp_command;
attr = MODATTR_EVENT_HANDLER_COMMAND;
break;
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
my_free(global_service_event_handler);
global_service_event_handler = temp_ptr;
global_service_event_handler_ptr = temp_command;
attr = MODATTR_EVENT_HANDLER_COMMAND;
break;
case CMD_CHANGE_HOST_EVENT_HANDLER:
my_free(temp_host->event_handler);
temp_host->event_handler = temp_ptr;
temp_host->event_handler_ptr = temp_command;
attr = MODATTR_EVENT_HANDLER_COMMAND;
break;
case CMD_CHANGE_HOST_CHECK_COMMAND:
my_free(temp_host->host_check_command);
temp_host->host_check_command = temp_ptr;
temp_host->check_command_ptr = temp_command;
attr = MODATTR_CHECK_COMMAND;
break;
case CMD_CHANGE_HOST_CHECK_TIMEPERIOD:
my_free(temp_host->check_period);
temp_host->check_period = temp_ptr;
temp_host->check_period_ptr = temp_timeperiod;
attr = MODATTR_CHECK_TIMEPERIOD;
break;
case CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD:
my_free(temp_host->notification_period);
temp_host->notification_period = temp_ptr;
temp_host->notification_period_ptr = temp_timeperiod;
attr = MODATTR_NOTIFICATION_TIMEPERIOD;
break;
case CMD_CHANGE_SVC_EVENT_HANDLER:
my_free(temp_service->event_handler);
temp_service->event_handler = temp_ptr;
temp_service->event_handler_ptr = temp_command;
attr = MODATTR_EVENT_HANDLER_COMMAND;
break;
case CMD_CHANGE_SVC_CHECK_COMMAND:
my_free(temp_service->service_check_command);
temp_service->service_check_command = temp_ptr;
temp_service->check_command_ptr = temp_command;
attr = MODATTR_CHECK_COMMAND;
break;
case CMD_CHANGE_SVC_CHECK_TIMEPERIOD:
my_free(temp_service->check_period);
temp_service->check_period = temp_ptr;
temp_service->check_period_ptr = temp_timeperiod;
attr = MODATTR_CHECK_TIMEPERIOD;
break;
case CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD:
my_free(temp_service->notification_period);
temp_service->notification_period = temp_ptr;
temp_service->notification_period_ptr = temp_timeperiod;
attr = MODATTR_NOTIFICATION_TIMEPERIOD;
break;
case CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD:
my_free(temp_contact->host_notification_period);
temp_contact->host_notification_period = temp_ptr;
temp_contact->host_notification_period_ptr = temp_timeperiod;
hattr = MODATTR_NOTIFICATION_TIMEPERIOD;
break;
case CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD:
my_free(temp_contact->service_notification_period);
temp_contact->service_notification_period = temp_ptr;
temp_contact->service_notification_period_ptr = temp_timeperiod;
sattr = MODATTR_NOTIFICATION_TIMEPERIOD;
break;
default:
break;
}
/* send data to event broker and update status file */
switch(cmd) {
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
/* set the modified host attribute */
modified_host_process_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cmd, attr, modified_host_process_attributes, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update program status */
update_program_status(FALSE);
break;
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
/* set the modified service attribute */
modified_service_process_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cmd, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update program status */
update_program_status(FALSE);
break;
case CMD_CHANGE_SVC_EVENT_HANDLER:
case CMD_CHANGE_SVC_CHECK_COMMAND:
case CMD_CHANGE_SVC_CHECK_TIMEPERIOD:
case CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD:
/* set the modified service attribute */
temp_service->modified_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_service, cmd, attr, temp_service->modified_attributes, NULL);
#endif
/* update the status log with the service info */
update_service_status(temp_service, FALSE);
break;
case CMD_CHANGE_HOST_EVENT_HANDLER:
case CMD_CHANGE_HOST_CHECK_COMMAND:
case CMD_CHANGE_HOST_CHECK_TIMEPERIOD:
case CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD:
/* set the modified host attribute */
temp_host->modified_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_host, cmd, attr, temp_host->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(temp_host, FALSE);
break;
case CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD:
/* set the modified attributes */
temp_contact->modified_host_attributes |= hattr;
temp_contact->modified_service_attributes |= sattr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_contact, cmd, attr, temp_contact->modified_attributes, hattr, temp_contact->modified_host_attributes, sattr, temp_contact->modified_service_attributes, NULL);
#endif
/* update the status log with the contact info */
update_contact_status(temp_contact, FALSE);
break;
default:
break;
}
return OK;
}
/* changes a custom host or service variable */
int cmd_change_object_custom_var(int cmd, char *args) {
host *temp_host = NULL;
service *temp_service = NULL;
contact *temp_contact = NULL;
customvariablesmember *temp_customvariablesmember = NULL;
char *temp_ptr = NULL;
char *name1 = NULL;
char *name2 = NULL;
char *varname = NULL;
char *varvalue = NULL;
register int x = 0;
/* get the host or contact name */
if((temp_ptr = my_strtok(args, ";")) == NULL)
return ERROR;
if((name1 = (char *)strdup(temp_ptr)) == NULL)
return ERROR;
/* get the service description if necessary */
if(cmd == CMD_CHANGE_CUSTOM_SVC_VAR) {
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(name1);
return ERROR;
}
if((name2 = (char *)strdup(temp_ptr)) == NULL) {
my_free(name1);
return ERROR;
}
}
/* get the custom variable name */
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(name1);
my_free(name2);
return ERROR;
}
if((varname = (char *)strdup(temp_ptr)) == NULL) {
my_free(name1);
my_free(name2);
return ERROR;
}
/* get the custom variable value */
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(name1);
my_free(name2);
my_free(varname);
return ERROR;
}
if((varvalue = (char *)strdup(temp_ptr)) == NULL) {
my_free(name1);
my_free(name2);
my_free(varname);
return ERROR;
}
/* find the object */
switch(cmd) {
case CMD_CHANGE_CUSTOM_HOST_VAR:
if((temp_host = find_host(name1)) == NULL)
return ERROR;
temp_customvariablesmember = temp_host->custom_variables;
break;
case CMD_CHANGE_CUSTOM_SVC_VAR:
if((temp_service = find_service(name1, name2)) == NULL)
return ERROR;
temp_customvariablesmember = temp_service->custom_variables;
break;
case CMD_CHANGE_CUSTOM_CONTACT_VAR:
if((temp_contact = find_contact(name1)) == NULL)
return ERROR;
temp_customvariablesmember = temp_contact->custom_variables;
break;
default:
break;
}
/* capitalize the custom variable name */
for(x = 0; varname[x] != '\x0'; x++)
varname[x] = toupper(varname[x]);
/* find the proper variable */
for(; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
/* we found the variable, so update the value */
if(!strcmp(varname, temp_customvariablesmember->variable_name)) {
/* update the value */
if(temp_customvariablesmember->variable_value)
my_free(temp_customvariablesmember->variable_value);
temp_customvariablesmember->variable_value = (char *)strdup(varvalue);
/* mark the variable value as having been changed */
temp_customvariablesmember->has_been_modified = TRUE;
break;
}
}
/* free memory */
my_free(name1);
my_free(name2);
my_free(varname);
my_free(varvalue);
/* set the modified attributes and update the status of the object */
switch(cmd) {
case CMD_CHANGE_CUSTOM_HOST_VAR:
temp_host->modified_attributes |= MODATTR_CUSTOM_VARIABLE;
update_host_status(temp_host, FALSE);
break;
case CMD_CHANGE_CUSTOM_SVC_VAR:
temp_service->modified_attributes |= MODATTR_CUSTOM_VARIABLE;
update_service_status(temp_service, FALSE);
break;
case CMD_CHANGE_CUSTOM_CONTACT_VAR:
temp_contact->modified_attributes |= MODATTR_CUSTOM_VARIABLE;
update_contact_status(temp_contact, FALSE);
break;
default:
break;
}
return OK;
}
/* processes an external host command */
int cmd_process_external_commands_from_file(int cmd, char *args) {
char *fname = NULL;
char *temp_ptr = NULL;
int delete_file = FALSE;
/* get the file name */
if((temp_ptr = my_strtok(args, ";")) == NULL)
return ERROR;
if((fname = (char *)strdup(temp_ptr)) == NULL)
return ERROR;
/* find the deletion option */
if((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
my_free(fname);
return ERROR;
}
if(atoi(temp_ptr) == 0)
delete_file = FALSE;
else
delete_file = TRUE;
/* process the file */
process_external_commands_from_file(fname, delete_file);
/* free memory */
my_free(fname);
return OK;
}
/******************************************************************/
/*************** INTERNAL COMMAND IMPLEMENTATIONS ****************/
/******************************************************************/
/* temporarily disables a service check */
void disable_service_checks(service *svc) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* checks are already disabled */
if(svc->checks_enabled == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* disable the service check... */
svc->checks_enabled = FALSE;
svc->should_be_scheduled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* update the status log to reflect the new service state */
update_service_status(svc, FALSE);
return;
}
/* enables a service check */
void enable_service_checks(service *svc) {
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* checks are already enabled */
if(svc->checks_enabled == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* enable the service check... */
svc->checks_enabled = TRUE;
svc->should_be_scheduled = TRUE;
/* services with no check intervals don't get checked */
if(svc->check_interval == 0)
svc->should_be_scheduled = FALSE;
/* schedule a check for right now (or as soon as possible) */
time(&preferred_time);
if(check_time_against_period(preferred_time, svc->check_period_ptr) == ERROR) {
get_next_valid_time(preferred_time, &next_valid_time, svc->check_period_ptr);
svc->next_check = next_valid_time;
}
else
svc->next_check = preferred_time;
/* schedule a check if we should */
if(svc->should_be_scheduled == TRUE)
schedule_service_check(svc, svc->next_check, CHECK_OPTION_NONE);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* update the status log to reflect the new service state */
update_service_status(svc, FALSE);
return;
}
/* enable notifications on a program-wide basis */
void enable_all_notifications(void) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* bail out if we're already set... */
if(enable_notifications == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* update notification status */
enable_notifications = 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 notifications on a program-wide basis */
void disable_all_notifications(void) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* bail out if we're already set... */
if(enable_notifications == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* update notification status */
enable_notifications = 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;
}
/* enables notifications for a service */
void enable_service_notifications(service *svc) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(svc->notifications_enabled == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* enable the service notifications... */
svc->notifications_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* update the status log to reflect the new service state */
update_service_status(svc, FALSE);
return;
}
/* disables notifications for a service */
void disable_service_notifications(service *svc) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(svc->notifications_enabled == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* disable the service notifications... */
svc->notifications_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* update the status log to reflect the new service state */
update_service_status(svc, FALSE);
return;
}
/* enables notifications for a host */
void enable_host_notifications(host *hst) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(hst->notifications_enabled == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* enable the host notifications... */
hst->notifications_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* update the status log to reflect the new host state */
update_host_status(hst, FALSE);
return;
}
/* disables notifications for a host */
void disable_host_notifications(host *hst) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(hst->notifications_enabled == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* disable the host notifications... */
hst->notifications_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* update the status log to reflect the new host state */
update_host_status(hst, FALSE);
return;
}
/* enables notifications for all hosts and services "beyond" a given host */
void enable_and_propagate_notifications(host *hst, int level, int affect_top_host, int affect_hosts, int affect_services) {
host *child_host = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
hostsmember *temp_hostsmember = NULL;
/* enable notification for top level host */
if(affect_top_host == TRUE && level == 0)
enable_host_notifications(hst);
/* check all child hosts... */
for(temp_hostsmember = hst->child_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
if((child_host = temp_hostsmember->host_ptr) == NULL)
continue;
/* recurse... */
enable_and_propagate_notifications(child_host, level + 1, affect_top_host, affect_hosts, affect_services);
/* enable notifications for this host */
if(affect_hosts == TRUE)
enable_host_notifications(child_host);
/* enable notifications for all services on this host... */
if(affect_services == TRUE) {
for(temp_servicesmember = child_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
enable_service_notifications(temp_service);
}
}
}
return;
}
/* disables notifications for all hosts and services "beyond" a given host */
void disable_and_propagate_notifications(host *hst, int level, int affect_top_host, int affect_hosts, int affect_services) {
host *child_host = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
hostsmember *temp_hostsmember = NULL;
if(hst == NULL)
return;
/* disable notifications for top host */
if(affect_top_host == TRUE && level == 0)
disable_host_notifications(hst);
/* check all child hosts... */
for(temp_hostsmember = hst->child_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
if((child_host = temp_hostsmember->host_ptr) == NULL)
continue;
/* recurse... */
disable_and_propagate_notifications(child_host, level + 1, affect_top_host, affect_hosts, affect_services);
/* disable notifications for this host */
if(affect_hosts == TRUE)
disable_host_notifications(child_host);
/* disable notifications for all services on this host... */
if(affect_services == TRUE) {
for(temp_servicesmember = child_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
disable_service_notifications(temp_service);
}
}
}
return;
}
/* enables host notifications for a contact */
void enable_contact_host_notifications(contact *cntct) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(cntct->host_notifications_enabled == TRUE)
return;
/* set the attribute modified flag */
cntct->modified_host_attributes |= attr;
/* enable the host notifications... */
cntct->host_notifications_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cntct, CMD_NONE, MODATTR_NONE, cntct->modified_attributes, attr, cntct->modified_host_attributes, MODATTR_NONE, cntct->modified_service_attributes, NULL);
#endif
/* update the status log to reflect the new contact state */
update_contact_status(cntct, FALSE);
return;
}
/* disables host notifications for a contact */
void disable_contact_host_notifications(contact *cntct) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(cntct->host_notifications_enabled == FALSE)
return;
/* set the attribute modified flag */
cntct->modified_host_attributes |= attr;
/* enable the host notifications... */
cntct->host_notifications_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cntct, CMD_NONE, MODATTR_NONE, cntct->modified_attributes, attr, cntct->modified_host_attributes, MODATTR_NONE, cntct->modified_service_attributes, NULL);
#endif
/* update the status log to reflect the new contact state */
update_contact_status(cntct, FALSE);
return;
}
/* enables service notifications for a contact */
void enable_contact_service_notifications(contact *cntct) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(cntct->service_notifications_enabled == TRUE)
return;
/* set the attribute modified flag */
cntct->modified_service_attributes |= attr;
/* enable the host notifications... */
cntct->service_notifications_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cntct, CMD_NONE, MODATTR_NONE, cntct->modified_attributes, MODATTR_NONE, cntct->modified_host_attributes, attr, cntct->modified_service_attributes, NULL);
#endif
/* update the status log to reflect the new contact state */
update_contact_status(cntct, FALSE);
return;
}
/* disables service notifications for a contact */
void disable_contact_service_notifications(contact *cntct) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(cntct->service_notifications_enabled == FALSE)
return;
/* set the attribute modified flag */
cntct->modified_service_attributes |= attr;
/* enable the host notifications... */
cntct->service_notifications_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cntct, CMD_NONE, MODATTR_NONE, cntct->modified_attributes, MODATTR_NONE, cntct->modified_host_attributes, attr, cntct->modified_service_attributes, NULL);
#endif
/* update the status log to reflect the new contact state */
update_contact_status(cntct, FALSE);
return;
}
/* schedules downtime for all hosts "beyond" a given host */
void schedule_and_propagate_downtime(host *temp_host, 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) {
host *child_host = NULL;
hostsmember *temp_hostsmember = NULL;
/* check all child hosts... */
for(temp_hostsmember = temp_host->child_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
if((child_host = temp_hostsmember->host_ptr) == NULL)
continue;
/* recurse... */
schedule_and_propagate_downtime(child_host, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration);
/* schedule downtime for this host */
schedule_downtime(HOST_DOWNTIME, child_host->name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, NULL);
}
return;
}
/* acknowledges a host problem */
void acknowledge_host_problem(host *hst, char *ack_author, char *ack_data, int type, int notify, int persistent) {
time_t current_time = 0L;
/* cannot acknowledge a non-existent problem */
if(hst->current_state == HOST_UP)
return;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_acknowledgement_data(NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, HOST_ACKNOWLEDGEMENT, (void *)hst, ack_author, ack_data, type, notify, persistent, NULL);
#endif
/* send out an acknowledgement notification */
if(notify == TRUE)
host_notification(hst, NOTIFICATION_ACKNOWLEDGEMENT, ack_author, ack_data, NOTIFICATION_OPTION_NONE);
/* set the acknowledgement flag */
hst->problem_has_been_acknowledged = TRUE;
/* set the acknowledgement type */
hst->acknowledgement_type = (type == ACKNOWLEDGEMENT_STICKY) ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL;
/* update the status log with the host info */
update_host_status(hst, FALSE);
/* add a comment for the acknowledgement */
time(¤t_time);
add_new_host_comment(ACKNOWLEDGEMENT_COMMENT, hst->name, current_time, ack_author, ack_data, persistent, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, NULL);
return;
}
/* acknowledges a service problem */
void acknowledge_service_problem(service *svc, char *ack_author, char *ack_data, int type, int notify, int persistent) {
time_t current_time = 0L;
/* cannot acknowledge a non-existent problem */
if(svc->current_state == STATE_OK)
return;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_acknowledgement_data(NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_ACKNOWLEDGEMENT, (void *)svc, ack_author, ack_data, type, notify, persistent, NULL);
#endif
/* send out an acknowledgement notification */
if(notify == TRUE)
service_notification(svc, NOTIFICATION_ACKNOWLEDGEMENT, ack_author, ack_data, NOTIFICATION_OPTION_NONE);
/* set the acknowledgement flag */
svc->problem_has_been_acknowledged = TRUE;
/* set the acknowledgement type */
svc->acknowledgement_type = (type == ACKNOWLEDGEMENT_STICKY) ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL;
/* update the status log with the service info */
update_service_status(svc, FALSE);
/* add a comment for the acknowledgement */
time(¤t_time);
add_new_service_comment(ACKNOWLEDGEMENT_COMMENT, svc->host_name, svc->description, current_time, ack_author, ack_data, persistent, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, NULL);
return;
}
/* removes a host acknowledgement */
void remove_host_acknowledgement(host *hst) {
/* set the acknowledgement flag */
hst->problem_has_been_acknowledged = FALSE;
/* update the status log with the host info */
update_host_status(hst, FALSE);
/* remove any non-persistant comments associated with the ack */
delete_host_acknowledgement_comments(hst);
return;
}
/* removes a service acknowledgement */
void remove_service_acknowledgement(service *svc) {
/* set the acknowledgement flag */
svc->problem_has_been_acknowledged = FALSE;
/* update the status log with the service info */
update_service_status(svc, FALSE);
/* remove any non-persistant comments associated with the ack */
delete_service_acknowledgement_comments(svc);
return;
}
/* starts executing service checks */
void start_executing_service_checks(void) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* bail out if we're already executing services */
if(execute_service_checks == TRUE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service check execution flag */
execute_service_checks = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stops executing service checks */
void stop_executing_service_checks(void) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* bail out if we're already not executing services */
if(execute_service_checks == FALSE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service check execution flag */
execute_service_checks = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* starts accepting passive service checks */
void start_accepting_passive_service_checks(void) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* bail out if we're already accepting passive services */
if(accept_passive_service_checks == TRUE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service check flag */
accept_passive_service_checks = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stops accepting passive service checks */
void stop_accepting_passive_service_checks(void) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* bail out if we're already not accepting passive services */
if(accept_passive_service_checks == FALSE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service check flag */
accept_passive_service_checks = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* enables passive service checks for a particular service */
void enable_passive_service_checks(service *svc) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* no change */
if(svc->accept_passive_service_checks == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the passive check flag */
svc->accept_passive_service_checks = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* disables passive service checks for a particular service */
void disable_passive_service_checks(service *svc) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* no change */
if(svc->accept_passive_service_checks == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the passive check flag */
svc->accept_passive_service_checks = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* starts executing host checks */
void start_executing_host_checks(void) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* bail out if we're already executing hosts */
if(execute_host_checks == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host check execution flag */
execute_host_checks = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stops executing host checks */
void stop_executing_host_checks(void) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* bail out if we're already not executing hosts */
if(execute_host_checks == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host check execution flag */
execute_host_checks = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* starts accepting passive host checks */
void start_accepting_passive_host_checks(void) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* bail out if we're already accepting passive hosts */
if(accept_passive_host_checks == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host check flag */
accept_passive_host_checks = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stops accepting passive host checks */
void stop_accepting_passive_host_checks(void) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* bail out if we're already not accepting passive hosts */
if(accept_passive_host_checks == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host check flag */
accept_passive_host_checks = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* enables passive host checks for a particular host */
void enable_passive_host_checks(host *hst) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* no change */
if(hst->accept_passive_host_checks == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the passive check flag */
hst->accept_passive_host_checks = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* disables passive host checks for a particular host */
void disable_passive_host_checks(host *hst) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* no change */
if(hst->accept_passive_host_checks == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the passive check flag */
hst->accept_passive_host_checks = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* enables event handlers on a program-wide basis */
void start_using_event_handlers(void) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(enable_event_handlers == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* set the event handler flag */
enable_event_handlers = 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 with the program info */
update_program_status(FALSE);
return;
}
/* disables event handlers on a program-wide basis */
void stop_using_event_handlers(void) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(enable_event_handlers == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* set the event handler flag */
enable_event_handlers = 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 with the program info */
update_program_status(FALSE);
return;
}
/* enables the event handler for a particular service */
void enable_service_event_handler(service *svc) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(svc->event_handler_enabled == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the event handler flag */
svc->event_handler_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* disables the event handler for a particular service */
void disable_service_event_handler(service *svc) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(svc->event_handler_enabled == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the event handler flag */
svc->event_handler_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* enables the event handler for a particular host */
void enable_host_event_handler(host *hst) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(hst->event_handler_enabled == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the event handler flag */
hst->event_handler_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* disables the event handler for a particular host */
void disable_host_event_handler(host *hst) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(hst->event_handler_enabled == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the event handler flag */
hst->event_handler_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* disables checks of a particular host */
void disable_host_checks(host *hst) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* checks are already disabled */
if(hst->checks_enabled == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the host check flag */
hst->checks_enabled = FALSE;
hst->should_be_scheduled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* enables checks of a particular host */
void enable_host_checks(host *hst) {
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* checks are already enabled */
if(hst->checks_enabled == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the host check flag */
hst->checks_enabled = TRUE;
hst->should_be_scheduled = TRUE;
/* hosts with no check intervals don't get checked */
if(hst->check_interval == 0)
hst->should_be_scheduled = FALSE;
/* schedule a check for right now (or as soon as possible) */
time(&preferred_time);
if(check_time_against_period(preferred_time, hst->check_period_ptr) == ERROR) {
get_next_valid_time(preferred_time, &next_valid_time, hst->check_period_ptr);
hst->next_check = next_valid_time;
}
else
hst->next_check = preferred_time;
/* schedule a check if we should */
if(hst->should_be_scheduled == TRUE)
schedule_host_check(hst, hst->next_check, CHECK_OPTION_NONE);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* start obsessing over service check results */
void start_obsessing_over_service_checks(void) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(obsess_over_services == TRUE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service obsession flag */
obsess_over_services = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stop obsessing over service check results */
void stop_obsessing_over_service_checks(void) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(obsess_over_services == FALSE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service obsession flag */
obsess_over_services = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* start obsessing over host check results */
void start_obsessing_over_host_checks(void) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(obsess_over_hosts == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host obsession flag */
obsess_over_hosts = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stop obsessing over host check results */
void stop_obsessing_over_host_checks(void) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(obsess_over_hosts == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host obsession flag */
obsess_over_hosts = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* enables service freshness checking */
void enable_service_freshness_checks(void) {
unsigned long attr = MODATTR_FRESHNESS_CHECKS_ENABLED;
/* no change */
if(check_service_freshness == TRUE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the freshness check flag */
check_service_freshness = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* disables service freshness checking */
void disable_service_freshness_checks(void) {
unsigned long attr = MODATTR_FRESHNESS_CHECKS_ENABLED;
/* no change */
if(check_service_freshness == FALSE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the freshness check flag */
check_service_freshness = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* enables host freshness checking */
void enable_host_freshness_checks(void) {
unsigned long attr = MODATTR_FRESHNESS_CHECKS_ENABLED;
/* no change */
if(check_host_freshness == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the freshness check flag */
check_host_freshness = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* disables host freshness checking */
void disable_host_freshness_checks(void) {
unsigned long attr = MODATTR_FRESHNESS_CHECKS_ENABLED;
/* no change */
if(check_host_freshness == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the freshness check flag */
check_host_freshness = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* 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;
/* bail out if we're already set... */
if(process_performance_data == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
process_performance_data = 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 performance data on a program-wide basis */
void disable_performance_data(void) {
unsigned long attr = MODATTR_PERFORMANCE_DATA_ENABLED;
# /* bail out if we're already set... */
if(process_performance_data == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
process_performance_data = 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;
}
/* start obsessing over a particular service */
void start_obsessing_over_service(service *svc) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(svc->obsess_over_service == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the obsess over service flag */
svc->obsess_over_service = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* stop obsessing over a particular service */
void stop_obsessing_over_service(service *svc) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(svc->obsess_over_service == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the obsess over service flag */
svc->obsess_over_service = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* start obsessing over a particular host */
void start_obsessing_over_host(host *hst) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(hst->obsess_over_host == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the obsess over host flag */
hst->obsess_over_host = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* stop obsessing over a particular host */
void stop_obsessing_over_host(host *hst) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(hst->obsess_over_host == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the obsess over host flag */
hst->obsess_over_host = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* sets the current notification number for a specific host */
void set_host_notification_number(host *hst, int num) {
/* set the notification number */
hst->current_notification_number = num;
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* sets the current notification number for a specific service */
void set_service_notification_number(service *svc, int num) {
/* set the notification number */
svc->current_notification_number = num;
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* 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)
return;
log_debug_info(DEBUGL_CHECKS, 1, "Submitting passive host/service check results obtained from external commands...\n");
/* 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;
}
checkresult_file_fp = fdopen(checkresult_file_fd, "w");
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");
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);
/* 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;
}
nagios/base/config.c 0000664 0000000 0000000 00000266000 12210155146 0014662 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* CONFIG.C - Configuration input and verification routines for Nagios
*
* Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 12-14-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.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/broker.h"
#include "../include/nebmods.h"
#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;
extern char *nagios_user;
extern char *nagios_group;
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;
/******************************************************************/
/************** CONFIGURATION INPUT FUNCTIONS *********************/
/******************************************************************/
/* read all configuration data */
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);
if(result != OK)
return ERROR;
return OK;
}
/* process the main configuration file */
int read_main_config_file(char *main_config_file) {
char *input = NULL;
char *variable = NULL;
char *value = NULL;
char *error_message = NULL;
char *temp_ptr = NULL;
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;
mac = get_global_macros();
/* open the config file for reading */
if((thefile = mmap_fopen(main_config_file)) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Cannot open main configuration file '%s' for reading!", main_config_file);
return ERROR;
}
/* save the main config file macro */
my_free(mac->x[MACRO_MAINCONFIGFILE]);
if((mac->x[MACRO_MAINCONFIGFILE] = (char *)strdup(main_config_file)))
strip(mac->x[MACRO_MAINCONFIGFILE]);
/* process all lines in the config file */
while(1) {
/* free memory */
my_free(input);
my_free(variable);
my_free(value);
/* read the next line */
if((input = mmap_fgets_multiline(thefile)) == NULL)
break;
current_line = thefile->current_line;
strip(input);
/* skip blank lines and comments */
if(input[0] == '\x0' || input[0] == '#')
continue;
/* get the variable name */
if((temp_ptr = my_strtok(input, "=")) == NULL) {
asprintf(&error_message, "NULL variable");
error = TRUE;
break;
}
if((variable = (char *)strdup(temp_ptr)) == NULL) {
asprintf(&error_message, "malloc() error");
error = TRUE;
break;
}
/* get the value */
if((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
asprintf(&error_message, "NULL value");
error = TRUE;
break;
}
if((value = (char *)strdup(temp_ptr)) == NULL) {
asprintf(&error_message, "malloc() error");
error = TRUE;
break;
}
strip(variable);
strip(value);
/* process the variable/value */
if(!strcmp(variable, "resource_file")) {
/* save the macro */
my_free(mac->x[MACRO_RESOURCEFILE]);
mac->x[MACRO_RESOURCEFILE] = (char *)strdup(value);
/* process the resource file */
read_resource_file(value);
}
else if(!strcmp(variable, "log_file")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Log file is too long");
error = TRUE;
break;
}
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);
}
else if(!strcmp(variable, "debug_level"))
debug_level = atoi(value);
else if(!strcmp(variable, "debug_verbosity"))
debug_verbosity = atoi(value);
else if(!strcmp(variable, "debug_file")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Debug log file is too long");
error = TRUE;
break;
}
my_free(debug_file);
debug_file = (char *)strdup(value);
}
else if(!strcmp(variable, "max_debug_file_size"))
max_debug_file_size = strtoul(value, NULL, 0);
else if(!strcmp(variable, "command_file")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Command file is too long");
error = TRUE;
break;
}
my_free(command_file);
command_file = (char *)strdup(value);
/* save the macro */
my_free(mac->x[MACRO_COMMANDFILE]);
mac->x[MACRO_COMMANDFILE] = (char *)strdup(value);
}
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);
}
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);
}
else if(!strcmp(variable, "check_result_path")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Check result path is too long");
error = TRUE;
break;
}
if((tmpdir = opendir((char *)value)) == NULL) {
asprintf(&error_message, "Check result 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';
}
my_free(check_result_path);
check_result_path = (char *)strdup(temp_path);
}
else if(!strcmp(variable, "max_check_result_file_age"))
max_check_result_file_age = strtoul(value, NULL, 0);
else if(!strcmp(variable, "lock_file")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Lock file is too long");
error = TRUE;
break;
}
my_free(lock_file);
lock_file = (char *)strdup(value);
}
else if(!strcmp(variable, "global_host_event_handler")) {
my_free(global_host_event_handler);
global_host_event_handler = (char *)strdup(value);
}
else if(!strcmp(variable, "global_service_event_handler")) {
my_free(global_service_event_handler);
global_service_event_handler = (char *)strdup(value);
}
else if(!strcmp(variable, "ocsp_command")) {
my_free(ocsp_command);
ocsp_command = (char *)strdup(value);
}
else if(!strcmp(variable, "ochp_command")) {
my_free(ochp_command);
ochp_command = (char *)strdup(value);
}
else if(!strcmp(variable, "nagios_user")) {
my_free(nagios_user);
nagios_user = (char *)strdup(value);
}
else if(!strcmp(variable, "nagios_group")) {
my_free(nagios_group);
nagios_group = (char *)strdup(value);
}
else if(!strcmp(variable, "admin_email")) {
/* save the macro */
my_free(mac->x[MACRO_ADMINEMAIL]);
mac->x[MACRO_ADMINEMAIL] = (char *)strdup(value);
}
else if(!strcmp(variable, "admin_pager")) {
/* save the macro */
my_free(mac->x[MACRO_ADMINPAGER]);
mac->x[MACRO_ADMINPAGER] = (char *)strdup(value);
}
else if(!strcmp(variable, "use_syslog")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for use_syslog");
error = TRUE;
break;
}
use_syslog = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_notifications")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_notifications");
error = TRUE;
break;
}
log_notifications = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_service_retries")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_service_retries");
error = TRUE;
break;
}
log_service_retries = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_host_retries")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_host_retries");
error = TRUE;
break;
}
log_host_retries = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_event_handlers")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_event_handlers");
error = TRUE;
break;
}
log_event_handlers = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_external_commands")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_external_commands");
error = TRUE;
break;
}
log_external_commands = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_passive_checks")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_passive_checks");
error = TRUE;
break;
}
log_passive_checks = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_initial_states")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_initial_states");
error = TRUE;
break;
}
log_initial_states = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "retain_state_information")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for retain_state_information");
error = TRUE;
break;
}
retain_state_information = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "retention_update_interval")) {
retention_update_interval = atoi(value);
if(retention_update_interval < 0) {
asprintf(&error_message, "Illegal value for retention_update_interval");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "use_retained_program_state")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for use_retained_program_state");
error = TRUE;
break;
}
use_retained_program_state = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "use_retained_scheduling_info")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for use_retained_scheduling_info");
error = TRUE;
break;
}
use_retained_scheduling_info = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "retention_scheduling_horizon")) {
retention_scheduling_horizon = atoi(value);
if(retention_scheduling_horizon <= 0) {
asprintf(&error_message, "Illegal value for retention_scheduling_horizon");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "additional_freshness_latency"))
additional_freshness_latency = atoi(value);
else if(!strcmp(variable, "retained_host_attribute_mask"))
retained_host_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "retained_service_attribute_mask"))
retained_service_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "retained_process_host_attribute_mask"))
retained_process_host_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "retained_process_service_attribute_mask"))
retained_process_service_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "retained_contact_host_attribute_mask"))
retained_contact_host_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "retained_contact_service_attribute_mask"))
retained_contact_service_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "obsess_over_services")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for obsess_over_services");
error = TRUE;
break;
}
obsess_over_services = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "obsess_over_hosts")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for obsess_over_hosts");
error = TRUE;
break;
}
obsess_over_hosts = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "translate_passive_host_checks")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for translate_passive_host_checks");
error = TRUE;
break;
}
translate_passive_host_checks = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "passive_host_checks_are_soft"))
passive_host_checks_are_soft = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "service_check_timeout")) {
service_check_timeout = atoi(value);
if(service_check_timeout <= 0) {
asprintf(&error_message, "Illegal value for service_check_timeout");
error = TRUE;
break;
}
}
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;
break;
}
}
else if(!strcmp(variable, "host_check_timeout")) {
host_check_timeout = atoi(value);
if(host_check_timeout <= 0) {
asprintf(&error_message, "Illegal value for host_check_timeout");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "event_handler_timeout")) {
event_handler_timeout = atoi(value);
if(event_handler_timeout <= 0) {
asprintf(&error_message, "Illegal value for event_handler_timeout");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "notification_timeout")) {
notification_timeout = atoi(value);
if(notification_timeout <= 0) {
asprintf(&error_message, "Illegal value for notification_timeout");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "ocsp_timeout")) {
ocsp_timeout = atoi(value);
if(ocsp_timeout <= 0) {
asprintf(&error_message, "Illegal value for ocsp_timeout");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "ochp_timeout")) {
ochp_timeout = atoi(value);
if(ochp_timeout <= 0) {
asprintf(&error_message, "Illegal value for ochp_timeout");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "use_agressive_host_checking") || !strcmp(variable, "use_aggressive_host_checking")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for use_aggressive_host_checking");
error = TRUE;
break;
}
use_aggressive_host_checking = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "cached_host_check_horizon"))
cached_host_check_horizon = strtoul(value, NULL, 0);
else if(!strcmp(variable, "enable_predictive_host_dependency_checks"))
enable_predictive_host_dependency_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "cached_service_check_horizon"))
cached_service_check_horizon = strtoul(value, NULL, 0);
else if(!strcmp(variable, "enable_predictive_service_dependency_checks"))
enable_predictive_service_dependency_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "soft_state_dependencies")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for soft_state_dependencies");
error = TRUE;
break;
}
soft_state_dependencies = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_rotation_method")) {
if(!strcmp(value, "n"))
log_rotation_method = LOG_ROTATION_NONE;
else if(!strcmp(value, "h"))
log_rotation_method = LOG_ROTATION_HOURLY;
else if(!strcmp(value, "d"))
log_rotation_method = LOG_ROTATION_DAILY;
else if(!strcmp(value, "w"))
log_rotation_method = LOG_ROTATION_WEEKLY;
else if(!strcmp(value, "m"))
log_rotation_method = LOG_ROTATION_MONTHLY;
else {
asprintf(&error_message, "Illegal value for log_rotation_method");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "log_archive_path")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Log archive path too long");
error = TRUE;
break;
}
my_free(log_archive_path);
log_archive_path = (char *)strdup(value);
}
else if(!strcmp(variable, "enable_event_handlers"))
enable_event_handlers = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "enable_notifications"))
enable_notifications = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "execute_service_checks"))
execute_service_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "accept_passive_service_checks"))
accept_passive_service_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "execute_host_checks"))
execute_host_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "accept_passive_host_checks"))
accept_passive_host_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "service_inter_check_delay_method")) {
if(!strcmp(value, "n"))
service_inter_check_delay_method = ICD_NONE;
else if(!strcmp(value, "d"))
service_inter_check_delay_method = ICD_DUMB;
else if(!strcmp(value, "s"))
service_inter_check_delay_method = ICD_SMART;
else {
service_inter_check_delay_method = ICD_USER;
scheduling_info.service_inter_check_delay = strtod(value, NULL);
if(scheduling_info.service_inter_check_delay <= 0.0) {
asprintf(&error_message, "Illegal value for service_inter_check_delay_method");
error = TRUE;
break;
}
}
}
else if(!strcmp(variable, "max_service_check_spread")) {
strip(value);
max_service_check_spread = atoi(value);
if(max_service_check_spread < 1) {
asprintf(&error_message, "Illegal value for max_service_check_spread");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "host_inter_check_delay_method")) {
if(!strcmp(value, "n"))
host_inter_check_delay_method = ICD_NONE;
else if(!strcmp(value, "d"))
host_inter_check_delay_method = ICD_DUMB;
else if(!strcmp(value, "s"))
host_inter_check_delay_method = ICD_SMART;
else {
host_inter_check_delay_method = ICD_USER;
scheduling_info.host_inter_check_delay = strtod(value, NULL);
if(scheduling_info.host_inter_check_delay <= 0.0) {
asprintf(&error_message, "Illegal value for host_inter_check_delay_method");
error = TRUE;
break;
}
}
}
else if(!strcmp(variable, "max_host_check_spread")) {
max_host_check_spread = atoi(value);
if(max_host_check_spread < 1) {
asprintf(&error_message, "Illegal value for max_host_check_spread");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "service_interleave_factor")) {
if(!strcmp(value, "s"))
service_interleave_factor_method = ILF_SMART;
else {
service_interleave_factor_method = ILF_USER;
scheduling_info.service_interleave_factor = atoi(value);
if(scheduling_info.service_interleave_factor < 1)
scheduling_info.service_interleave_factor = 1;
}
}
else if(!strcmp(variable, "max_concurrent_checks")) {
max_parallel_service_checks = atoi(value);
if(max_parallel_service_checks < 0) {
asprintf(&error_message, "Illegal value for max_concurrent_checks");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "check_result_reaper_frequency") || !strcmp(variable, "service_reaper_frequency")) {
check_reaper_interval = atoi(value);
if(check_reaper_interval < 1) {
asprintf(&error_message, "Illegal value for check_result_reaper_frequency");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "max_check_result_reaper_time")) {
max_check_reaper_time = atoi(value);
if(max_check_reaper_time < 1) {
asprintf(&error_message, "Illegal value for max_check_result_reaper_time");
error = TRUE;
break;
}
}
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;
}
}
else if(!strcmp(variable, "interval_length")) {
interval_length = atoi(value);
if(interval_length < 1) {
asprintf(&error_message, "Illegal value for interval_length");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "check_external_commands")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for check_external_commands");
error = TRUE;
break;
}
check_external_commands = (atoi(value) > 0) ? TRUE : FALSE;
}
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;
}
}
else if(!strcmp(variable, "check_for_orphaned_services")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for check_for_orphaned_services");
error = TRUE;
break;
}
check_orphaned_services = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "check_for_orphaned_hosts")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for check_for_orphaned_hosts");
error = TRUE;
break;
}
check_orphaned_hosts = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "check_service_freshness")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for check_service_freshness");
error = TRUE;
break;
}
check_service_freshness = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "check_host_freshness")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for check_host_freshness");
error = TRUE;
break;
}
check_host_freshness = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "service_freshness_check_interval") || !strcmp(variable, "freshness_check_interval")) {
service_freshness_check_interval = atoi(value);
if(service_freshness_check_interval <= 0) {
asprintf(&error_message, "Illegal value for service_freshness_check_interval");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "host_freshness_check_interval")) {
host_freshness_check_interval = atoi(value);
if(host_freshness_check_interval <= 0) {
asprintf(&error_message, "Illegal value for host_freshness_check_interval");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "auto_reschedule_checks")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for auto_reschedule_checks");
error = TRUE;
break;
}
auto_reschedule_checks = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "auto_rescheduling_interval")) {
auto_rescheduling_interval = atoi(value);
if(auto_rescheduling_interval <= 0) {
asprintf(&error_message, "Illegal value for auto_rescheduling_interval");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "auto_rescheduling_window")) {
auto_rescheduling_window = atoi(value);
if(auto_rescheduling_window <= 0) {
asprintf(&error_message, "Illegal value for auto_rescheduling_window");
error = TRUE;
break;
}
}
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) {
asprintf(&error_message, "Illegal value for status_update_interval");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "time_change_threshold")) {
time_change_threshold = atoi(value);
if(time_change_threshold <= 5) {
asprintf(&error_message, "Illegal value for time_change_threshold");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "process_performance_data"))
process_performance_data = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "enable_flap_detection"))
enable_flap_detection = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "enable_failure_prediction"))
enable_failure_prediction = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "low_service_flap_threshold")) {
low_service_flap_threshold = strtod(value, NULL);
if(low_service_flap_threshold <= 0.0 || low_service_flap_threshold >= 100.0) {
asprintf(&error_message, "Illegal value for low_service_flap_threshold");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "high_service_flap_threshold")) {
high_service_flap_threshold = strtod(value, NULL);
if(high_service_flap_threshold <= 0.0 || high_service_flap_threshold > 100.0) {
asprintf(&error_message, "Illegal value for high_service_flap_threshold");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "low_host_flap_threshold")) {
low_host_flap_threshold = strtod(value, NULL);
if(low_host_flap_threshold <= 0.0 || low_host_flap_threshold >= 100.0) {
asprintf(&error_message, "Illegal value for low_host_flap_threshold");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "high_host_flap_threshold")) {
high_host_flap_threshold = strtod(value, NULL);
if(high_host_flap_threshold <= 0.0 || high_host_flap_threshold > 100.0) {
asprintf(&error_message, "Illegal value for high_host_flap_threshold");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "date_format")) {
if(!strcmp(value, "euro"))
date_format = DATE_FORMAT_EURO;
else if(!strcmp(value, "iso8601"))
date_format = DATE_FORMAT_ISO8601;
else if(!strcmp(value, "strict-iso8601"))
date_format = DATE_FORMAT_STRICT_ISO8601;
else
date_format = DATE_FORMAT_US;
}
else if(!strcmp(variable, "use_timezone")) {
my_free(use_timezone);
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"))
event_broker_options = BROKER_EVERYTHING;
else
event_broker_options = strtoul(value, NULL, 0);
}
else if(!strcmp(variable, "illegal_object_name_chars"))
illegal_object_chars = (char *)strdup(value);
else if(!strcmp(variable, "illegal_macro_output_chars"))
illegal_output_chars = (char *)strdup(value);
else if(!strcmp(variable, "broker_module")) {
modptr = strtok(value, " \n");
argptr = strtok(NULL, "\n");
#ifdef USE_EVENT_BROKER
neb_add_module(modptr, argptr, TRUE);
#endif
}
else if(!strcmp(variable, "use_regexp_matching"))
use_regexp_matches = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "use_true_regexp_matching"))
use_true_regexp_matching = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "daemon_dumps_core")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for daemon_dumps_core");
error = TRUE;
break;
}
daemon_dumps_core = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "use_large_installation_tweaks")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for use_large_installation_tweaks ");
error = TRUE;
break;
}
use_large_installation_tweaks = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "enable_environment_macros"))
enable_environment_macros = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "free_child_process_memory"))
free_child_process_memory = (atoi(value) > 0) ? TRUE : FALSE;
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;
}
else if(!strcmp(variable, "external_command_buffer_slots"))
external_command_buffer_slots = atoi(value);
else if(!strcmp(variable, "check_for_updates"))
check_for_updates = (atoi(value) > 0) ? TRUE : FALSE;
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")) {
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);
}
/* 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, "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.");
}
/* 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;
}
/* we don't know what this variable is... */
else {
asprintf(&error_message, "UNKNOWN VARIABLE");
error = TRUE;
break;
}
}
/* 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;
if(child_processes_fork_twice == -1)
child_processes_fork_twice = (use_large_installation_tweaks == TRUE) ? FALSE : TRUE;
/* handle errors */
if(error == TRUE) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error in configuration file '%s' - Line %d (%s)", main_config_file, current_line, (error_message == NULL) ? "NULL" : error_message);
return ERROR;
}
/* free leftover memory and close the file */
my_free(input);
mmap_fclose(thefile);
/* free memory */
my_free(error_message);
my_free(input);
my_free(variable);
my_free(value);
/* make sure a log file has been specified */
strip(log_file);
if(!strcmp(log_file, "")) {
if(daemon_mode == FALSE)
printf("Error: Log file is not specified anywhere in main config file '%s'!\n", main_config_file);
return ERROR;
}
return OK;
}
/* processes macros in resource file */
int read_resource_file(char *resource_file) {
char *input = NULL;
char *variable = NULL;
char *value = NULL;
char *temp_ptr = NULL;
mmapfile *thefile = NULL;
int current_line = 1;
int error = FALSE;
int user_index = 0;
if((thefile = mmap_fopen(resource_file)) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Cannot open resource file '%s' for reading!", resource_file);
return ERROR;
}
/* process all lines in the resource file */
while(1) {
/* free memory */
my_free(input);
my_free(variable);
my_free(value);
/* read the next line */
if((input = mmap_fgets_multiline(thefile)) == NULL)
break;
current_line = thefile->current_line;
/* skip blank lines and comments */
if(input[0] == '#' || input[0] == '\x0' || input[0] == '\n' || input[0] == '\r')
continue;
strip(input);
/* get the variable name */
if((temp_ptr = my_strtok(input, "=")) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable - Line %d of resource file '%s'", current_line, resource_file);
error = TRUE;
break;
}
if((variable = (char *)strdup(temp_ptr)) == NULL) {
error = TRUE;
break;
}
/* get the value */
if((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable value - Line %d of resource file '%s'", current_line, resource_file);
error = TRUE;
break;
}
if((value = (char *)strdup(temp_ptr)) == NULL) {
error = TRUE;
break;
}
/* what should we do with the variable/value pair? */
/* check for macro declarations */
if(variable[0] == '$' && variable[strlen(variable) - 1] == '$') {
/* $USERx$ macro declarations */
if(strstr(variable, "$USER") == variable && strlen(variable) > 5) {
user_index = atoi(variable + 5) - 1;
if(user_index >= 0 && user_index < MAX_USER_MACROS) {
my_free(macro_user[user_index]);
macro_user[user_index] = (char *)strdup(value);
}
}
}
}
/* free leftover memory and close the file */
my_free(input);
mmap_fclose(thefile);
/* free memory */
my_free(variable);
my_free(value);
if(error == TRUE)
return ERROR;
return OK;
}
/****************************************************************/
/**************** CONFIG VERIFICATION FUNCTIONS *****************/
/****************************************************************/
/* 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];
double runtime[4];
int temp_path_fd = -1;
if(test_scheduling == TRUE)
gettimeofday(&tv[0], NULL);
/********************************************/
/* check object relationships */
/********************************************/
pre_flight_object_check(&warnings, &errors);
if(test_scheduling == TRUE)
gettimeofday(&tv[1], NULL);
/********************************************/
/* check for circular paths between hosts */
/********************************************/
pre_flight_circular_check(&warnings, &errors);
if(test_scheduling == TRUE)
gettimeofday(&tv[2], NULL);
/********************************************/
/* check global event handler commands... */
/********************************************/
if(verify_config == TRUE)
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);
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);
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)
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);
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);
errors++;
}
/* save the pointer to the command for later */
ochp_command_ptr = temp_command;
my_free(buf);
}
/**************************************************/
/* check various settings... */
/**************************************************/
if(verify_config == TRUE)
printf("Checking misc settings...\n");
/* check if we can write to temp_path */
asprintf(&buf, "%s/nagiosXXXXXX", temp_path);
if((temp_path_fd = mkstemp(buf)) == -1) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "\tError: Unable to write to temp_path ('%s') - %s\n", temp_path, strerror(errno));
errors++;
}
else {
close(temp_path_fd);
remove(buf);
}
my_free(buf);
/* check if we can write to check_result_path */
asprintf(&buf, "%s/nagiosXXXXXX", check_result_path);
if((temp_path_fd = mkstemp(buf)) == -1) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "\tError: Unable to write to check_result_path ('%s') - %s\n", check_result_path, strerror(errno));
errors++;
}
else {
close(temp_path_fd);
remove(buf);
}
my_free(buf);
/* warn if user didn't specify any illegal macro output chars */
if(illegal_output_chars == NULL) {
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;
}
}
if(verify_config == TRUE) {
printf("\n");
printf("Total Warnings: %d\n", warnings);
printf("Total Errors: %d\n", errors);
}
if(test_scheduling == TRUE)
gettimeofday(&tv[3], NULL);
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[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("----------------------------------\n");
printf("Object Relationships: %.6lf sec\n", runtime[0]);
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("\n\n");
}
return (errors > 0) ? ERROR : OK;
}
/* do a pre-flight check to make sure object relationships make sense */
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;
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;
#ifdef TEST
void *ptr = NULL;
char *buf1 = "";
char *buf2 = "";
buf1 = "temptraxe1";
buf2 = "Probe 2";
for(temp_se = get_first_serviceescalation_by_service(buf1, buf2, &ptr); temp_se != NULL; temp_se = get_next_serviceescalation_by_service(buf1, buf2, &ptr)) {
printf("FOUND ESCALATION FOR SVC '%s'/'%s': %d-%d/%.3f, PTR=%p\n", buf1, buf2, temp_se->first_notification, temp_se->last_notification, temp_se->notification_interval, ptr);
}
for(temp_he = get_first_hostescalation_by_host(buf1, &ptr); temp_he != NULL; temp_he = get_next_hostescalation_by_host(buf1, &ptr)) {
printf("FOUND ESCALATION FOR HOST '%s': %d-%d/%d, PTR=%p\n", buf1, temp_he->first_notification, temp_he->last_notification, temp_he->notification_interval, ptr);
}
#endif
/* bail out if we aren't supposed to verify object relationships */
if(verify_object_relationships == FALSE)
return OK;
/*****************************************/
/* 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++;
}
total_objects = 0;
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);
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);
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) {
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);
warnings++;
}
/* verify service check timeperiod */
if(temp_service->check_period == NULL) {
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) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' has no notification time period defined!", temp_service->description, temp_service->host_name);
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);
errors++;
}
/* save the pointer to the notification timeperiod for later */
temp_service->notification_period_ptr = temp_timeperiod;
}
/* see if the notification interval is less than the check interval */
if(temp_service->notification_interval < temp_service->check_interval && temp_service->notification_interval != 0) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' has a notification interval less than its check interval! Notifications are only re-sent after checks are made, so the effective notification interval will be that of the check interval.", temp_service->description, temp_service->host_name);
warnings++;
}
/* check for illegal characters in service description */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_service->description) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The description string for service '%s' on host '%s' contains one or more illegal characters.", temp_service->description, temp_service->host_name);
errors++;
}
}
}
if(verify_config == TRUE)
printf("\tChecked %d services.\n", total_objects);
/*****************************************/
/* 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++;
}
total_objects = 0;
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;
}
/* 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);
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);
errors++;
}
/* save the pointer to the check command for later */
temp_host->check_command_ptr = temp_command;
my_free(buf);
}
/* check host check timeperiod */
if(temp_host->check_period != NULL) {
temp_timeperiod = find_timeperiod(temp_host->check_period);
if(temp_timeperiod == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Check period '%s' specified for host '%s' is not defined anywhere!", temp_host->check_period, temp_host->name);
errors++;
}
/* save the pointer to the check timeperiod for later */
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);
warnings++;
}
/* check notification timeperiod */
if(temp_host->notification_period != NULL) {
temp_timeperiod = find_timeperiod(temp_host->notification_period);
if(temp_timeperiod == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Notification period '%s' specified for host '%s' is not defined anywhere!", temp_host->notification_period, temp_host->name);
errors++;
}
/* save the pointer to the notification timeperiod for later */
temp_host->notification_period_ptr = temp_timeperiod;
}
/* check all parent parent host */
for(temp_hostsmember = temp_host->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
if((temp_host2 = find_host(temp_hostsmember->host_name)) == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: '%s' is not a valid parent for host '%s'!", temp_hostsmember->host_name, temp_host->name);
errors++;
}
/* save the parent host pointer for later */
temp_hostsmember->host_ptr = temp_host2;
/* add a reverse (child) link to make searches faster later on */
add_child_link_to_host(temp_host2, temp_host);
}
/* check for sane recovery options */
if(temp_host->notify_on_recovery == TRUE && temp_host->notify_on_down == FALSE && temp_host->notify_on_unreachable == FALSE) {
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++;
}
/* check for illegal characters in host name */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_host->name) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of host '%s' contains one or more illegal characters.", temp_host->name);
errors++;
}
}
}
if(verify_config == TRUE)
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) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of hostgroup '%s' contains one or more illegal characters.", temp_hostgroup->group_name);
errors++;
}
}
}
if(verify_config == TRUE)
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) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of servicegroup '%s' contains one or more illegal characters.", temp_servicegroup->group_name);
errors++;
}
}
}
if(verify_config == TRUE)
printf("\tChecked %d service groups.\n", total_objects);
/*****************************************/
/* 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++;
}
for(temp_contact = contact_list, total_objects = 0; temp_contact != NULL; temp_contact = temp_contact->next, total_objects++) {
/* check service notification commands */
if(temp_contact->service_notification_commands == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' has no service notification commands defined!", temp_contact->name);
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);
}
/* check host notification commands */
if(temp_contact->host_notification_commands == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' has no host notification commands defined!", temp_contact->name);
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);
}
/* check service notification timeperiod */
if(temp_contact->service_notification_period == NULL) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Contact '%s' has no service notification time period defined!", temp_contact->name);
warnings++;
}
else {
temp_timeperiod = find_timeperiod(temp_contact->service_notification_period);
if(temp_timeperiod == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service notification period '%s' specified for contact '%s' is not defined anywhere!", temp_contact->service_notification_period, temp_contact->name);
errors++;
}
/* save the pointer to the service notification timeperiod for later */
temp_contact->service_notification_period_ptr = temp_timeperiod;
}
/* check host notification timeperiod */
if(temp_contact->host_notification_period == NULL) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Contact '%s' has no host notification time period defined!", temp_contact->name);
warnings++;
}
else {
temp_timeperiod = find_timeperiod(temp_contact->host_notification_period);
if(temp_timeperiod == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host notification period '%s' specified for contact '%s' is not defined anywhere!", temp_contact->host_notification_period, temp_contact->name);
errors++;
}
/* save the pointer to the host notification timeperiod for later */
temp_contact->host_notification_period_ptr = temp_timeperiod;
}
/* 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) {
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) {
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++;
}
/* check for illegal characters in contact name */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_contact->name) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of contact '%s' contains one or more illegal characters.", temp_contact->name);
errors++;
}
}
}
if(verify_config == TRUE)
printf("\tChecked %d contacts.\n", total_objects);
/*****************************************/
/* 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) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of contact group '%s' contains one or more illegal characters.", temp_contactgroup->group_name);
errors++;
}
}
}
if(verify_config == TRUE)
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 */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_command->name) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of command '%s' contains one or more illegal characters.", temp_command->name);
errors++;
}
}
}
if(verify_config == TRUE)
printf("\tChecked %d commands.\n", total_objects);
/*****************************************/
/* 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 */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_timeperiod->name) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of time period '%s' contains one or more illegal characters.", temp_timeperiod->name);
errors++;
}
}
/* check for valid timeperiod names in exclusion list */
for(temp_timeperiodexclusion = temp_timeperiod->exclusions; temp_timeperiodexclusion != NULL; temp_timeperiodexclusion = temp_timeperiodexclusion->next) {
temp_timeperiod2 = find_timeperiod(temp_timeperiodexclusion->timeperiod_name);
if(temp_timeperiod2 == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Excluded time period '%s' specified in timeperiod '%s' is not defined anywhere!", temp_timeperiodexclusion->timeperiod_name, temp_timeperiod->name);
errors++;
}
/* save the timeperiod pointer for later */
temp_timeperiodexclusion->timeperiod_ptr = temp_timeperiod2;
}
}
if(verify_config == TRUE)
printf("\tChecked %d time periods.\n", total_objects);
/* update warning and error count */
*w += warnings;
*e += errors;
return (errors > 0) ? ERROR : OK;
}
/* dfs status values */
#define DFS_UNCHECKED 0 /* default value */
#define DFS_TEMP_CHECKED 1 /* check just one time */
#define DFS_OK 2 /* no problem */
#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)
/**
* Modified version of Depth-first Search
* http://en.wikipedia.org/wiki/Depth-first_search
*/
static int dfs_host_path(host *root) {
hostsmember *child = NULL;
if(!root)
return DFS_NEAR_LOOP;
if(dfs_get_status(root) != DFS_UNCHECKED)
return dfs_get_status(root);
/* Mark the root temporary checked */
dfs_set_status(root, DFS_TEMP_CHECKED);
/* We are scanning the children */
for(child = root->child_hosts; child != NULL; child = child->next) {
int child_status = dfs_get_status(child->host_ptr);
/* If a child is not checked, check it */
if(child_status == DFS_UNCHECKED)
child_status = dfs_host_path(child->host_ptr);
/* If a child already temporary checked, its a problem,
* loop inside, and its a acked status */
if(child_status == DFS_TEMP_CHECKED) {
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);
}
}
/*
* If root have been modified, do not set it OK
* A node is OK if and only if all of his children are OK
* If it does not have child, goes ok
*/
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;
int errors = 0;
/* bail out if we aren't supposed to verify circular paths */
if(verify_circular_paths == FALSE)
return OK;
/********************************************/
/* 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);
}
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(dfs_host_path(temp_host) == DFS_LOOPY)
errors = 1;
}
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);
}
/********************************************/
/* check for circular dependencies */
/********************************************/
if(verify_config == TRUE)
printf("Checking for circular host and service dependencies...\n");
/* 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 notification 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, 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 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++;
}
}
/* update warning and error count */
*w += warnings;
*e += errors;
return (errors > 0) ? ERROR : OK;
}
nagios/base/events.c 0000664 0000000 0000000 00000203165 12210155146 0014724 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* EVENTS.C - Timed event functions for Nagios
*
* Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 08-28-2010
*
* 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/downtime.h"
#include "../include/comments.h"
#include "../include/statusdata.h"
#include "../include/nagios.h"
#include "../include/broker.h"
#include "../include/sretention.h"
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;
/******************************************************************/
/************ EVENT SCHEDULING/HANDLING FUNCTIONS *****************/
/******************************************************************/
/* 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;
int mult_factor = 0;
int is_valid_time = 0;
time_t next_valid_time = 0L;
int schedule_check = 0;
double max_inter_check_delay = 0.0;
struct timeval tv[9];
double runtime[9];
log_debug_info(DEBUGL_FUNCTIONS, 0, "init_timing_loop() start\n");
/* get the time right now */
time(¤t_time);
/******** GET BASIC HOST/SERVICE INFO ********/
scheduling_info.total_services = 0;
scheduling_info.total_scheduled_services = 0;
scheduling_info.total_hosts = 0;
scheduling_info.total_scheduled_hosts = 0;
scheduling_info.average_services_per_host = 0.0;
scheduling_info.average_scheduled_services_per_host = 0.0;
scheduling_info.average_service_execution_time = 0.0;
scheduling_info.service_check_interval_total = 0;
scheduling_info.average_service_inter_check_delay = 0.0;
scheduling_info.host_check_interval_total = 0;
scheduling_info.average_host_inter_check_delay = 0.0;
if(test_scheduling == TRUE)
gettimeofday(&tv[0], NULL);
/* get info on service checks to be scheduled */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
schedule_check = TRUE;
/* service has no check interval */
if(temp_service->check_interval == 0)
schedule_check = FALSE;
/* active checks are disabled */
if(temp_service->checks_enabled == FALSE)
schedule_check = FALSE;
/* are there any valid times this service can be checked? */
is_valid_time = check_time_against_period(current_time, temp_service->check_period_ptr);
if(is_valid_time == ERROR) {
get_next_valid_time(current_time, &next_valid_time, temp_service->check_period_ptr);
if(current_time == next_valid_time)
schedule_check = FALSE;
}
if(schedule_check == TRUE) {
scheduling_info.total_scheduled_services++;
/* used later in inter-check delay calculations */
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);
}
else {
temp_service->should_be_scheduled = FALSE;
log_debug_info(DEBUGL_EVENTS, 1, "Service '%s' on host '%s' should not be scheduled.\n", temp_service->description, temp_service->host_name);
}
scheduling_info.total_services++;
}
if(test_scheduling == TRUE)
gettimeofday(&tv[1], NULL);
/* get info on host checks to be scheduled */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
schedule_check = TRUE;
/* host has no check interval */
if(temp_host->check_interval == 0)
schedule_check = FALSE;
/* active checks are disabled */
if(temp_host->checks_enabled == FALSE)
schedule_check = FALSE;
/* are there any valid times this host can be checked? */
is_valid_time = check_time_against_period(current_time, temp_host->check_period_ptr);
if(is_valid_time == ERROR) {
get_next_valid_time(current_time, &next_valid_time, temp_host->check_period_ptr);
if(current_time == next_valid_time)
schedule_check = FALSE;
}
if(schedule_check == TRUE) {
scheduling_info.total_scheduled_hosts++;
/* this is used later in inter-check delay calculations */
scheduling_info.host_check_interval_total += temp_host->check_interval;
}
else {
temp_host->should_be_scheduled = FALSE;
log_debug_info(DEBUGL_EVENTS, 1, "Host '%s' should not be scheduled.\n", temp_host->name);
}
scheduling_info.total_hosts++;
}
if(test_scheduling == TRUE)
gettimeofday(&tv[2], NULL);
scheduling_info.average_services_per_host = (double)((double)scheduling_info.total_services / (double)scheduling_info.total_hosts);
scheduling_info.average_scheduled_services_per_host = (double)((double)scheduling_info.total_scheduled_services / (double)scheduling_info.total_hosts);
/* adjust the check interval total to correspond to the interval length */
scheduling_info.service_check_interval_total = (scheduling_info.service_check_interval_total * interval_length);
/* calculate the average check interval for services */
scheduling_info.average_service_check_interval = (double)((double)scheduling_info.service_check_interval_total / (double)scheduling_info.total_scheduled_services);
/******** DETERMINE SERVICE SCHEDULING PARAMS ********/
log_debug_info(DEBUGL_EVENTS, 2, "Determining service scheduling parameters...");
/* default max service check spread (in minutes) */
scheduling_info.max_service_check_spread = max_service_check_spread;
/* how should we determine the service inter-check delay to use? */
switch(service_inter_check_delay_method) {
case ICD_NONE:
/* don't spread checks out - useful for testing parallelization code */
scheduling_info.service_inter_check_delay = 0.0;
break;
case ICD_DUMB:
/* be dumb and just schedule checks 1 second apart */
scheduling_info.service_inter_check_delay = 1.0;
break;
case ICD_USER:
/* the user specified a delay, so don't try to calculate one */
break;
case ICD_SMART:
default:
/* be smart and calculate the best delay to use to minimize local load... */
if(scheduling_info.total_scheduled_services > 0 && scheduling_info.service_check_interval_total > 0) {
/* calculate the average inter check delay (in seconds) needed to evenly space the service checks out */
scheduling_info.average_service_inter_check_delay = (double)(scheduling_info.average_service_check_interval / (double)scheduling_info.total_scheduled_services);
/* set the global inter check delay value */
scheduling_info.service_inter_check_delay = scheduling_info.average_service_inter_check_delay;
/* calculate max inter check delay and see if we should use that instead */
max_inter_check_delay = (double)((scheduling_info.max_service_check_spread * 60.0) / (double)scheduling_info.total_scheduled_services);
if(scheduling_info.service_inter_check_delay > max_inter_check_delay)
scheduling_info.service_inter_check_delay = max_inter_check_delay;
}
else
scheduling_info.service_inter_check_delay = 0.0;
log_debug_info(DEBUGL_EVENTS, 1, "Total scheduled service checks: %d\n", scheduling_info.total_scheduled_services);
log_debug_info(DEBUGL_EVENTS, 1, "Average service check interval: %0.2f sec\n", scheduling_info.average_service_check_interval);
log_debug_info(DEBUGL_EVENTS, 1, "Service inter-check delay: %0.2f sec\n", scheduling_info.service_inter_check_delay);
}
/* how should we determine the service interleave factor? */
switch(service_interleave_factor_method) {
case ILF_USER:
/* the user supplied a value, so don't do any calculation */
break;
case ILF_SMART:
default:
/* protect against a divide by zero problem - shouldn't happen, but just in case... */
if(scheduling_info.total_hosts == 0)
scheduling_info.total_hosts = 1;
scheduling_info.service_interleave_factor = (int)(ceil(scheduling_info.average_scheduled_services_per_host));
log_debug_info(DEBUGL_EVENTS, 1, "Total scheduled service checks: %d\n", scheduling_info.total_scheduled_services);
log_debug_info(DEBUGL_EVENTS, 1, "Total hosts: %d\n", scheduling_info.total_hosts);
log_debug_info(DEBUGL_EVENTS, 1, "Service Interleave factor: %d\n", scheduling_info.service_interleave_factor);
}
/* calculate number of service interleave blocks */
if(scheduling_info.service_interleave_factor == 0)
total_interleave_blocks = scheduling_info.total_scheduled_services;
else
total_interleave_blocks = (int)ceil((double)scheduling_info.total_scheduled_services / (double)scheduling_info.service_interleave_factor);
scheduling_info.first_service_check = (time_t)0L;
scheduling_info.last_service_check = (time_t)0L;
log_debug_info(DEBUGL_EVENTS, 1, "Total scheduled services: %d\n", scheduling_info.total_scheduled_services);
log_debug_info(DEBUGL_EVENTS, 1, "Service Interleave factor: %d\n", scheduling_info.service_interleave_factor);
log_debug_info(DEBUGL_EVENTS, 1, "Total service interleave blocks: %d\n", total_interleave_blocks);
log_debug_info(DEBUGL_EVENTS, 1, "Service inter-check delay: %2.1f\n", scheduling_info.service_inter_check_delay);
if(test_scheduling == TRUE)
gettimeofday(&tv[3], NULL);
/******** SCHEDULE SERVICE CHECKS ********/
log_debug_info(DEBUGL_EVENTS, 2, "Scheduling service checks...");
/* determine check times for service checks (with interleaving to minimize remote load) */
current_interleave_block = 0;
for(temp_service = service_list; temp_service != NULL && scheduling_info.service_interleave_factor > 0;) {
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) {
log_debug_info(DEBUGL_EVENTS, 2, "Service check should not be scheduled.\n");
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
* were supposed to happen while we weren't running...
* We check to make sure the check isn't scheduled to run
* far in the future to make sure checks who've hade their
* timeperiods changed during the restart aren't left
* 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)) {
log_debug_info(DEBUGL_EVENTS, 2, "Service is already scheduled to be checked in the future: %s\n", ctime(&temp_service->next_check));
continue;
}
/* interleave block index should only be increased when we find a schedulable service */
/* moved from for() loop 11/05/05 EG */
interleave_block_index++;
mult_factor = current_interleave_block + (interleave_block_index * total_interleave_blocks);
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));
log_debug_info(DEBUGL_EVENTS, 2, "Preferred Check Time: %lu --> %s", (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));
get_next_valid_time(temp_service->next_check, &next_valid_time, temp_service->check_period_ptr);
temp_service->next_check = next_valid_time;
}
log_debug_info(DEBUGL_EVENTS, 2, "Actual Check Time: %lu --> %s", (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;
if(temp_service->next_check > scheduling_info.last_service_check)
scheduling_info.last_service_check = temp_service->next_check;
}
current_interleave_block++;
}
if(test_scheduling == TRUE)
gettimeofday(&tv[4], NULL);
/* add scheduled service checks to event queue */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
/* Nagios XI/NDOUtils MOD */
/* 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) {
/* passive checks are an exception if a forced check was scheduled before Nagios was restarted */
if(!(temp_service->checks_enabled == FALSE && temp_service->next_check != (time_t)0L && (temp_service->check_options & CHECK_OPTION_FORCE_EXECUTION)))
continue;
}
/* 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);
}
if(test_scheduling == TRUE)
gettimeofday(&tv[5], NULL);
/******** DETERMINE HOST SCHEDULING PARAMS ********/
log_debug_info(DEBUGL_EVENTS, 2, "Determining host scheduling parameters...");
scheduling_info.first_host_check = (time_t)0L;
scheduling_info.last_host_check = (time_t)0L;
/* default max host check spread (in minutes) */
scheduling_info.max_host_check_spread = max_host_check_spread;
/* how should we determine the host inter-check delay to use? */
switch(host_inter_check_delay_method) {
case ICD_NONE:
/* don't spread checks out */
scheduling_info.host_inter_check_delay = 0.0;
break;
case ICD_DUMB:
/* be dumb and just schedule checks 1 second apart */
scheduling_info.host_inter_check_delay = 1.0;
break;
case ICD_USER:
/* the user specified a delay, so don't try to calculate one */
break;
case ICD_SMART:
default:
/* be smart and calculate the best delay to use to minimize local load... */
if(scheduling_info.total_scheduled_hosts > 0 && scheduling_info.host_check_interval_total > 0) {
/* adjust the check interval total to correspond to the interval length */
scheduling_info.host_check_interval_total = (scheduling_info.host_check_interval_total * interval_length);
/* calculate the average check interval for hosts */
scheduling_info.average_host_check_interval = (double)((double)scheduling_info.host_check_interval_total / (double)scheduling_info.total_scheduled_hosts);
/* calculate the average inter check delay (in seconds) needed to evenly space the host checks out */
scheduling_info.average_host_inter_check_delay = (double)(scheduling_info.average_host_check_interval / (double)scheduling_info.total_scheduled_hosts);
/* set the global inter check delay value */
scheduling_info.host_inter_check_delay = scheduling_info.average_host_inter_check_delay;
/* calculate max inter check delay and see if we should use that instead */
max_inter_check_delay = (double)((scheduling_info.max_host_check_spread * 60.0) / (double)scheduling_info.total_scheduled_hosts);
if(scheduling_info.host_inter_check_delay > max_inter_check_delay)
scheduling_info.host_inter_check_delay = max_inter_check_delay;
}
else
scheduling_info.host_inter_check_delay = 0.0;
log_debug_info(DEBUGL_EVENTS, 2, "Total scheduled host checks: %d\n", scheduling_info.total_scheduled_hosts);
log_debug_info(DEBUGL_EVENTS, 2, "Host check interval total: %lu\n", scheduling_info.host_check_interval_total);
log_debug_info(DEBUGL_EVENTS, 2, "Average host check interval: %0.2f sec\n", scheduling_info.average_host_check_interval);
log_debug_info(DEBUGL_EVENTS, 2, "Host inter-check delay: %0.2f sec\n", scheduling_info.host_inter_check_delay);
}
if(test_scheduling == TRUE)
gettimeofday(&tv[6], NULL);
/******** SCHEDULE HOST CHECKS ********/
log_debug_info(DEBUGL_EVENTS, 2, "Scheduling host checks...");
/* determine check times for host checks */
mult_factor = 0;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
log_debug_info(DEBUGL_EVENTS, 2, "Host '%s'\n", temp_host->name);
/* skip hosts that shouldn't be scheduled */
if(temp_host->should_be_scheduled == FALSE) {
log_debug_info(DEBUGL_EVENTS, 2, "Host check should not be scheduled.\n");
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));
log_debug_info(DEBUGL_EVENTS, 2, "Preferred Check Time: %lu --> %s", (unsigned long)temp_host->next_check, ctime(&temp_host->next_check));
/* make sure the host can actually be scheduled at this time */
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;
}
log_debug_info(DEBUGL_EVENTS, 2, "Actual Check Time: %lu --> %s", (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;
if(temp_host->next_check > scheduling_info.last_host_check)
scheduling_info.last_host_check = temp_host->next_check;
mult_factor++;
}
if(test_scheduling == TRUE)
gettimeofday(&tv[7], NULL);
/* add scheduled host checks to event queue */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
/* Nagios XI/NDOUtils Mod */
/* 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) {
/* passive checks are an exception if a forced check was scheduled before Nagios was restarted */
if(!(temp_host->checks_enabled == FALSE && temp_host->next_check != (time_t)0L && (temp_host->check_options & CHECK_OPTION_FORCE_EXECUTION)))
continue;
}
/* 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);
}
if(test_scheduling == TRUE)
gettimeofday(&tv[8], NULL);
/******** SCHEDULE MISC EVENTS ********/
/* add a host and service check rescheduling event */
if(auto_reschedule_checks == TRUE)
schedule_new_event(EVENT_RESCHEDULE_CHECKS, TRUE, current_time + auto_rescheduling_interval, TRUE, auto_rescheduling_interval, NULL, TRUE, NULL, NULL, 0);
/* add a check result reaper event */
schedule_new_event(EVENT_CHECK_REAPER, TRUE, current_time + check_reaper_interval, TRUE, check_reaper_interval, NULL, TRUE, NULL, NULL, 0);
/* add an orphaned check event */
if(check_orphaned_services == TRUE || check_orphaned_hosts == TRUE)
schedule_new_event(EVENT_ORPHAN_CHECK, TRUE, current_time + DEFAULT_ORPHAN_CHECK_INTERVAL, TRUE, DEFAULT_ORPHAN_CHECK_INTERVAL, NULL, TRUE, NULL, NULL, 0);
/* add a service result "freshness" check event */
if(check_service_freshness == TRUE)
schedule_new_event(EVENT_SFRESHNESS_CHECK, TRUE, current_time + service_freshness_check_interval, TRUE, service_freshness_check_interval, NULL, TRUE, NULL, NULL, 0);
/* add a host result "freshness" check event */
if(check_host_freshness == TRUE)
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);
}
/* add a log rotation event if necessary */
if(log_rotation_method != LOG_ROTATION_NONE)
schedule_new_event(EVENT_LOG_ROTATION, TRUE, get_next_log_rotation_time(), TRUE, 0, (void *)get_next_log_rotation_time, TRUE, NULL, NULL, 0);
/* add a retention data save event if needed */
if(retain_state_information == TRUE && retention_update_interval > 0)
schedule_new_event(EVENT_RETENTION_SAVE, TRUE, current_time + (retention_update_interval * 60), TRUE, (retention_update_interval * 60), NULL, TRUE, NULL, NULL, 0);
if(test_scheduling == 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);
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);
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] = (double)((double)(tv[4].tv_sec - tv[3].tv_sec) + (double)((tv[4].tv_usec - tv[3].tv_usec) / 1000.0) / 1000.0);
runtime[4] = (double)((double)(tv[5].tv_sec - tv[4].tv_sec) + (double)((tv[5].tv_usec - tv[4].tv_usec) / 1000.0) / 1000.0);
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[8].tv_sec - tv[0].tv_sec) + (double)((tv[8].tv_usec - tv[0].tv_usec) / 1000.0) / 1000.0);
printf("EVENT SCHEDULING TIMES\n");
printf("-------------------------------------\n");
printf("Get service info: %.6lf sec\n", runtime[0]);
printf("Get host info info: %.6lf sec\n", runtime[1]);
printf("Get service params: %.6lf sec\n", runtime[2]);
printf("Schedule service times: %.6lf sec\n", runtime[3]);
printf("Schedule service events: %.6lf sec\n", runtime[4]);
printf("Get host params: %.6lf sec\n", runtime[5]);
printf("Schedule host times: %.6lf sec\n", runtime[6]);
printf("Schedule host events: %.6lf sec\n", runtime[7]);
printf(" ============\n");
printf("TOTAL: %.6lf sec\n", runtime[8]);
printf("\n\n");
}
log_debug_info(DEBUGL_FUNCTIONS, 0, "init_timing_loop() end\n");
return;
}
/* 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");
printf("is listed below. This information assumes that you are going\n");
printf("to start running Nagios with your current config files.\n\n");
printf("HOST SCHEDULING INFORMATION\n");
printf("---------------------------\n");
printf("Total hosts: %d\n", scheduling_info.total_hosts);
printf("Total scheduled hosts: %d\n", scheduling_info.total_scheduled_hosts);
printf("Host inter-check delay method: ");
if(host_inter_check_delay_method == ICD_NONE)
printf("NONE\n");
else if(host_inter_check_delay_method == ICD_DUMB)
printf("DUMB\n");
else if(host_inter_check_delay_method == ICD_SMART) {
printf("SMART\n");
printf("Average host check interval: %.2f sec\n", scheduling_info.average_host_check_interval);
}
else
printf("USER-SUPPLIED VALUE\n");
printf("Host inter-check delay: %.2f sec\n", scheduling_info.host_inter_check_delay);
printf("Max host check spread: %d min\n", scheduling_info.max_host_check_spread);
printf("First scheduled check: %s", (scheduling_info.total_scheduled_hosts == 0) ? "N/A\n" : ctime(&scheduling_info.first_host_check));
printf("Last scheduled check: %s", (scheduling_info.total_scheduled_hosts == 0) ? "N/A\n" : ctime(&scheduling_info.last_host_check));
printf("\n\n");
printf("SERVICE SCHEDULING INFORMATION\n");
printf("-------------------------------\n");
printf("Total services: %d\n", scheduling_info.total_services);
printf("Total scheduled services: %d\n", scheduling_info.total_scheduled_services);
printf("Service inter-check delay method: ");
if(service_inter_check_delay_method == ICD_NONE)
printf("NONE\n");
else if(service_inter_check_delay_method == ICD_DUMB)
printf("DUMB\n");
else if(service_inter_check_delay_method == ICD_SMART) {
printf("SMART\n");
printf("Average service check interval: %.2f sec\n", scheduling_info.average_service_check_interval);
}
else
printf("USER-SUPPLIED VALUE\n");
printf("Inter-check delay: %.2f sec\n", scheduling_info.service_inter_check_delay);
printf("Interleave factor method: %s\n", (service_interleave_factor_method == ILF_USER) ? "USER-SUPPLIED VALUE" : "SMART");
if(service_interleave_factor_method == ILF_SMART)
printf("Average services per host: %.2f\n", scheduling_info.average_services_per_host);
printf("Service interleave factor: %d\n", scheduling_info.service_interleave_factor);
printf("Max service check spread: %d min\n", scheduling_info.max_service_check_spread);
printf("First scheduled check: %s", ctime(&scheduling_info.first_service_check));
printf("Last scheduled check: %s", ctime(&scheduling_info.last_service_check));
printf("\n\n");
printf("CHECK PROCESSING INFORMATION\n");
printf("----------------------------\n");
printf("Check result reaper interval: %d sec\n", check_reaper_interval);
printf("Max concurrent service checks: ");
if(max_parallel_service_checks == 0)
printf("Unlimited\n");
else
printf("%d\n", max_parallel_service_checks);
printf("\n\n");
printf("PERFORMANCE SUGGESTIONS\n");
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(suggestions == 0)
printf("I have no suggestions - things look okay.\n");
printf("\n");
return;
}
/* 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;
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);
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, " High Priority: %s\n",
(high_priority ? "Yes" : "No"));
log_debug_info(DEBUGL_EVENTS, 0, " Run Time: %s\n",
run_time_string);
log_debug_info(DEBUGL_EVENTS, 0, " Recurring: %s\n",
(recurring ? "Yes" : "No"));
log_debug_info(DEBUGL_EVENTS, 0, " Event Interval: %lu\n",
event_interval);
log_debug_info(DEBUGL_EVENTS, 0, " Compensate for Time Change: %s\n",
(compensate_for_time_change ? "Yes" : "No"));
log_debug_info(DEBUGL_EVENTS, 0, " Event Options: %d\n",
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));
if(new_event != NULL) {
new_event->event_type = event_type;
new_event->event_data = event_data;
new_event->event_args = event_args;
new_event->event_options = event_options;
new_event->run_time = run_time;
new_event->recurring = recurring;
new_event->event_interval = event_interval;
new_event->timing_func = timing_func;
new_event->compensate_for_time_change = compensate_for_time_change;
}
else
return ERROR;
/* add the event to the event list */
add_event(new_event, event_list, event_list_tail);
return OK;
}
/* reschedule an event in order of execution time */
void reschedule_event(timed_event *event, timed_event **event_list, timed_event **event_list_tail) {
time_t current_time = 0L;
time_t (*timingfunc)(void);
log_debug_info(DEBUGL_FUNCTIONS, 0, "reschedule_event()\n");
/* reschedule recurring events... */
if(event->recurring == TRUE) {
/* use custom timing function */
if(event->timing_func != NULL) {
timingfunc = event->timing_func;
event->run_time = (*timingfunc)();
}
/* normal recurring events */
else {
event->run_time = event->run_time + event->event_interval;
time(¤t_time);
if(event->run_time < current_time)
event->run_time = current_time;
}
}
/* add the event to the event list */
add_event(event, event_list, event_list_tail);
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;
log_debug_info(DEBUGL_FUNCTIONS, 0, "add_event()\n");
event->next = NULL;
event->prev = NULL;
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;
}
/* 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;
}
}
}
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_timed_event(NEBTYPE_TIMEDEVENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, event, NULL);
#endif
return;
}
/* 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;
#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)
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(!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 there was only one event in the list, we're already
* done, just as if there were events before and efter the
* deleted event
*/
}
/* this is the main event handler loop */
int event_execution_loop(void) {
timed_event *temp_event = NULL;
timed_event sleep_event;
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;
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) {
/* 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);
/* hey, wait a second... we traveled back in time! */
if(current_time < last_time)
compensate_for_system_time_change((unsigned long)last_time, (unsigned long)current_time);
/* else if the time advanced over the specified threshold, try and compensate... */
else if((current_time - last_time) >= time_change_threshold)
compensate_for_system_time_change((unsigned long)last_time, (unsigned long)current_time);
/* 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 */
if((unsigned long)(current_time - last_status_update) > 5) {
last_status_update = current_time;
update_program_status(FALSE);
}
}
log_debug_info(DEBUGL_FUNCTIONS, 0, "event_execution_loop() end\n");
return OK;
}
/* handles a timed event */
int handle_timed_event(timed_event *event) {
host *temp_host = NULL;
service *temp_service = NULL;
void (*userfunc)(void *);
struct timeval tv;
double latency = 0.0;
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_timed_event() start\n");
#ifdef USE_EVENT_BROKER
/* send event data to broker */
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));
/* how should we handle the event? */
switch(event->event_type) {
case EVENT_SERVICE_CHECK:
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;
case EVENT_HOST_CHECK:
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();
break;
case EVENT_LOG_ROTATION:
log_debug_info(DEBUGL_EVENTS, 0, "** Log File Rotation Event\n");
/* rotate the log file */
rotate_log_file(event->run_time);
break;
case EVENT_PROGRAM_SHUTDOWN:
log_debug_info(DEBUGL_EVENTS, 0, "** Program Shutdown Event\n");
/* set the shutdown flag */
sigshutdown = TRUE;
/* log the shutdown */
logit(NSLOG_PROCESS_INFO, TRUE, "PROGRAM_SHUTDOWN event encountered, shutting down...\n");
break;
case EVENT_PROGRAM_RESTART:
log_debug_info(DEBUGL_EVENTS, 0, "** Program Restart Event\n");
/* set the restart flag */
sigrestart = TRUE;
/* log the restart */
logit(NSLOG_PROCESS_INFO, TRUE, "PROGRAM_RESTART event encountered, restarting...\n");
break;
case EVENT_CHECK_REAPER:
log_debug_info(DEBUGL_EVENTS, 0, "** Check Result Reaper\n");
/* reap host and service check results */
reap_check_results();
break;
case EVENT_ORPHAN_CHECK:
log_debug_info(DEBUGL_EVENTS, 0, "** Orphaned Host and Service Check Event\n");
/* check for orphaned hosts and services */
if(check_orphaned_hosts == TRUE)
check_for_orphaned_hosts();
if(check_orphaned_services == TRUE)
check_for_orphaned_services();
break;
case EVENT_RETENTION_SAVE:
log_debug_info(DEBUGL_EVENTS, 0, "** Retention Data Save Event\n");
/* save state retention data */
save_state_information(TRUE);
break;
case EVENT_STATUS_SAVE:
log_debug_info(DEBUGL_EVENTS, 0, "** Status Data Save Event\n");
/* save all status data (program, host, and service) */
update_all_status_data();
break;
case EVENT_SCHEDULED_DOWNTIME:
log_debug_info(DEBUGL_EVENTS, 0, "** Scheduled Downtime Event\n");
/* process scheduled downtime info */
if(event->event_data) {
handle_scheduled_downtime_by_id(*(unsigned long *)event->event_data);
free(event->event_data);
event->event_data = NULL;
}
break;
case EVENT_SFRESHNESS_CHECK:
log_debug_info(DEBUGL_EVENTS, 0, "** Service Result Freshness Check Event\n");
/* check service result freshness */
check_service_result_freshness();
break;
case EVENT_HFRESHNESS_CHECK:
log_debug_info(DEBUGL_EVENTS, 0, "** Host Result Freshness Check Event\n");
/* check host result freshness */
check_host_result_freshness();
break;
case EVENT_EXPIRE_DOWNTIME:
log_debug_info(DEBUGL_EVENTS, 0, "** Expire Downtime Event\n");
/* check for expired scheduled downtime entries */
check_for_expired_downtime();
break;
case EVENT_RESCHEDULE_CHECKS:
/* adjust scheduling of host and service checks */
log_debug_info(DEBUGL_EVENTS, 0, "** Reschedule Checks Event\n");
adjust_check_scheduling();
break;
case EVENT_EXPIRE_COMMENT:
log_debug_info(DEBUGL_EVENTS, 0, "** Expire Comment Event\n");
/* check for expired comment */
check_for_expired_comment((unsigned long)event->event_data);
break;
case EVENT_CHECK_PROGRAM_UPDATE:
log_debug_info(DEBUGL_EVENTS, 0, "** Check For Program Update\n");
/* check for new versions of Nagios */
check_for_nagios_updates(FALSE, TRUE);
break;
case EVENT_USER_FUNCTION:
log_debug_info(DEBUGL_EVENTS, 0, "** User Function Event\n");
/* run a user-defined function */
if(event->event_data != NULL) {
userfunc = event->event_data;
(*userfunc)(event->event_args);
}
break;
default:
break;
}
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_timed_event() end\n");
return OK;
}
/* adjusts scheduling of host and service checks */
void adjust_check_scheduling(void) {
timed_event *temp_event = NULL;
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;
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;
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;
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) {
/* 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++;
}
/* 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);
*/
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;
}
/*
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)
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;
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);
}
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;
}
/* 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");
return;
}
/* 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);
log_debug_info(DEBUGL_FUNCTIONS, 0, "compensate_for_system_time_change() start\n");
/* we moved back in time... */
if(last_time > current_time) {
time_difference = last_time - current_time;
get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds);
log_debug_info(DEBUGL_EVENTS, 0, "Detected a backwards time change of %dd %dh %dm %ds.\n", days, hours, minutes, seconds);
}
/* we moved into the future... */
else {
time_difference = current_time - last_time;
get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds);
log_debug_info(DEBUGL_EVENTS, 0, "Detected a forwards time change of %dd %dh %dm %ds.\n", days, hours, minutes, seconds);
}
/* 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");
/* 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 service timestamps */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_notification);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_check);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->next_check);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_state_change);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_hard_state_change);
/* recalculate next re-notification time */
temp_service->next_notification = get_next_service_notification_time(temp_service, temp_service->last_notification);
/* update the status data */
update_service_status(temp_service, FALSE);
}
/* 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_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);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_hard_state_change);
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);
/* update the status data */
update_host_status(temp_host, FALSE);
}
/* 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);
return;
}
/* 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) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "adjust_timestamp_for_time_change()\n");
/* we shouldn't do anything with epoch values */
if(*ts == (time_t)0)
return;
/* we moved back in time... */
if(last_time > current_time) {
/* we can't precede the UNIX epoch */
if(time_difference > (unsigned long)*ts)
*ts = (time_t)0;
else
*ts = (time_t)(*ts - time_difference);
}
/* we moved into the future... */
else
*ts = (time_t)(*ts + time_difference);
return;
}
nagios/base/flapping.c 0000664 0000000 0000000 00000065767 12210155146 0015236 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* 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:
*
* 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/objects.h"
#include "../include/comments.h"
#include "../include/statusdata.h"
#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 ********************/
/******************************************************************/
/* detects service flapping */
void check_for_service_flapping(service *svc, int update, int allow_flapstart_notification) {
int update_history = TRUE;
int is_flapping = FALSE;
register int x = 0;
register int y = 0;
int last_state_history_value = STATE_OK;
double curved_changes = 0.0;
double curved_percent_change = 0.0;
double low_threshold = 0.0;
double high_threshold = 0.0;
double low_curve_value = 0.75;
double high_curve_value = 1.25;
/* large install tweaks skips all flap detection logic - including state change calculation */
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_service_flapping()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Checking service '%s' on host '%s' for flapping...\n", svc->description, svc->host_name);
/* if this is a soft service state and not a soft recovery, don't record this in the history */
/* only hard states and soft recoveries get recorded for flap detection */
if(svc->state_type == SOFT_STATE && svc->current_state != STATE_OK)
return;
/* what threshold values should we use (global or service-specific)? */
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;
update_history = update;
/* 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)
update_history = FALSE;
}
/* record current service state */
if(update_history == TRUE) {
/* record the current state in the state history */
svc->state_history[svc->state_history_index] = svc->current_state;
/* increment state history index to next available slot */
svc->state_history_index++;
if(svc->state_history_index >= MAX_STATE_HISTORY_ENTRIES)
svc->state_history_index = 0;
}
/* calculate overall and curved percent state changes */
for(x = 0, y = svc->state_history_index; x < MAX_STATE_HISTORY_ENTRIES; x++) {
if(x == 0) {
last_state_history_value = svc->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
continue;
}
if(last_state_history_value != svc->state_history[y])
curved_changes += (((double)(x - 1) * (high_curve_value - low_curve_value)) / ((double)(MAX_STATE_HISTORY_ENTRIES - 2))) + low_curve_value;
last_state_history_value = svc->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
}
/* calculate overall percent change in state */
curved_percent_change = (double)(((double)curved_changes * 100.0) / (double)(MAX_STATE_HISTORY_ENTRIES - 1));
svc->percent_state_change = curved_percent_change;
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)
return;
/* are we flapping, undecided, or what?... */
/* we're undecided, so don't change the current flap state */
if(curved_percent_change > low_threshold && curved_percent_change < high_threshold)
return;
/* we're below the lower bound, so we're not flapping */
else if(curved_percent_change <= low_threshold)
is_flapping = FALSE;
/* else we're above the upper bound, so we are flapping */
else if(curved_percent_change >= high_threshold)
is_flapping = TRUE;
log_debug_info(DEBUGL_FLAPPING, 1, "Service %s flapping (%.2f%% state change).\n", (is_flapping == TRUE) ? "is" : "is not", curved_percent_change);
/* did the service just start flapping? */
if(is_flapping == TRUE && svc->is_flapping == FALSE)
set_service_flap(svc, curved_percent_change, high_threshold, low_threshold, allow_flapstart_notification);
/* 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);
return;
}
/* detects host flapping */
void check_for_host_flapping(host *hst, int update, int actual_check, int allow_flapstart_notification) {
int update_history = TRUE;
int is_flapping = FALSE;
register int x = 0;
register int y = 0;
int last_state_history_value = HOST_UP;
unsigned long wait_threshold = 0L;
double curved_changes = 0.0;
double curved_percent_change = 0.0;
time_t current_time = 0L;
double low_threshold = 0.0;
double high_threshold = 0.0;
double low_curve_value = 0.75;
double high_curve_value = 1.25;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_host_flapping()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Checking host '%s' for flapping...\n", hst->name);
time(¤t_time);
/* period to wait for updating archived state info if we have no state change */
if(hst->total_services == 0)
wait_threshold = hst->notification_interval * interval_length;
else
wait_threshold = (hst->total_service_check_interval * interval_length) / hst->total_services;
update_history = update;
/* 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)
update_history = FALSE;
}
/* if we didn't have an actual check, only update if we've waited long enough */
if(update_history == TRUE && actual_check == FALSE && (current_time - hst->last_state_history_update) < wait_threshold) {
update_history = FALSE;
}
/* what thresholds should we use (global or host-specific)? */
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;
/* record current host state */
if(update_history == TRUE) {
/* update the last record time */
hst->last_state_history_update = current_time;
/* record the current state in the state history */
hst->state_history[hst->state_history_index] = hst->current_state;
/* increment state history index to next available slot */
hst->state_history_index++;
if(hst->state_history_index >= MAX_STATE_HISTORY_ENTRIES)
hst->state_history_index = 0;
}
/* calculate overall changes in state */
for(x = 0, y = hst->state_history_index; x < MAX_STATE_HISTORY_ENTRIES; x++) {
if(x == 0) {
last_state_history_value = hst->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
continue;
}
if(last_state_history_value != hst->state_history[y])
curved_changes += (((double)(x - 1) * (high_curve_value - low_curve_value)) / ((double)(MAX_STATE_HISTORY_ENTRIES - 2))) + low_curve_value;
last_state_history_value = hst->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
}
/* calculate overall percent change in state */
curved_percent_change = (double)(((double)curved_changes * 100.0) / (double)(MAX_STATE_HISTORY_ENTRIES - 1));
hst->percent_state_change = curved_percent_change;
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)
return;
/* are we flapping, undecided, or what?... */
/* we're undecided, so don't change the current flap state */
if(curved_percent_change > low_threshold && curved_percent_change < high_threshold)
return;
/* we're below the lower bound, so we're not flapping */
else if(curved_percent_change <= low_threshold)
is_flapping = FALSE;
/* else we're above the upper bound, so we are flapping */
else if(curved_percent_change >= high_threshold)
is_flapping = TRUE;
log_debug_info(DEBUGL_FLAPPING, 1, "Host %s flapping (%.2f%% state change).\n", (is_flapping == TRUE) ? "is" : "is not", curved_percent_change);
/* did the host just start flapping? */
if(is_flapping == TRUE && hst->is_flapping == FALSE)
set_host_flap(hst, curved_percent_change, high_threshold, low_threshold, allow_flapstart_notification);
/* 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);
return;
}
/******************************************************************/
/********************* FLAP HANDLING FUNCTIONS ********************/
/******************************************************************/
/* handles a service that is flapping */
void set_service_flap(service *svc, double percent_change, double high_threshold, double low_threshold, int allow_flapstart_notification) {
char *temp_buffer = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "set_service_flap()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Service '%s' on host '%s' started flapping!\n", svc->description, svc->host_name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_RUNTIME_WARNING, FALSE, "SERVICE FLAPPING ALERT: %s;%s;STARTED; Service appears to have started flapping (%2.1f%% change >= %2.1f%% threshold)\n", svc->host_name, svc->description, percent_change, high_threshold);
/* add a non-persistent comment to the service */
asprintf(&temp_buffer, "Notifications for this service are being suppressed because it was detected as having been flapping between different states (%2.1f%% change >= %2.1f%% threshold). When the service state stabilizes and the flapping stops, notifications will be re-enabled.", percent_change, high_threshold);
add_new_service_comment(FLAPPING_COMMENT, svc->host_name, svc->description, time(NULL), "(Nagios Process)", temp_buffer, 0, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, &(svc->flapping_comment_id));
my_free(temp_buffer);
/* set the flapping indicator */
svc->is_flapping = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_FLAPPING, svc, percent_change, high_threshold, low_threshold, NULL);
#endif
/* see if we should check to send a recovery notification out when flapping stops */
if(svc->current_state != STATE_OK && svc->current_notification_number > 0)
svc->check_flapping_recovery_notification = TRUE;
else
svc->check_flapping_recovery_notification = FALSE;
/* send a notification */
if(allow_flapstart_notification == TRUE)
service_notification(svc, NOTIFICATION_FLAPPINGSTART, NULL, NULL, NOTIFICATION_OPTION_NONE);
return;
}
/* handles a service that has stopped flapping */
void clear_service_flap(service *svc, double percent_change, double high_threshold, double low_threshold) {
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);
/* delete the comment we added earlier */
if(svc->flapping_comment_id != 0)
delete_service_comment(svc->flapping_comment_id);
svc->flapping_comment_id = 0;
/* clear the flapping indicator */
svc->is_flapping = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
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);
/* 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;
return;
}
/* handles a host that is flapping */
void set_host_flap(host *hst, double percent_change, double high_threshold, double low_threshold, int allow_flapstart_notification) {
char *temp_buffer = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "set_host_flap()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Host '%s' started flapping!\n", hst->name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_RUNTIME_WARNING, FALSE, "HOST FLAPPING ALERT: %s;STARTED; Host appears to have started flapping (%2.1f%% change > %2.1f%% threshold)\n", hst->name, percent_change, high_threshold);
/* add a non-persistent comment to the host */
asprintf(&temp_buffer, "Notifications for this host are being suppressed because it was detected as having been flapping between different states (%2.1f%% change > %2.1f%% threshold). When the host state stabilizes and the flapping stops, notifications will be re-enabled.", percent_change, high_threshold);
add_new_host_comment(FLAPPING_COMMENT, hst->name, time(NULL), "(Nagios Process)", temp_buffer, 0, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, &(hst->flapping_comment_id));
my_free(temp_buffer);
/* set the flapping indicator */
hst->is_flapping = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_FLAPPING, hst, percent_change, high_threshold, low_threshold, NULL);
#endif
/* see if we should check to send a recovery notification out when flapping stops */
if(hst->current_state != HOST_UP && hst->current_notification_number > 0)
hst->check_flapping_recovery_notification = TRUE;
else
hst->check_flapping_recovery_notification = FALSE;
/* send a notification */
if(allow_flapstart_notification == TRUE)
host_notification(hst, NOTIFICATION_FLAPPINGSTART, NULL, NULL, NOTIFICATION_OPTION_NONE);
return;
}
/* handles a host that has stopped flapping */
void clear_host_flap(host *hst, double percent_change, double high_threshold, double low_threshold) {
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);
/* delete the comment we added earlier */
if(hst->flapping_comment_id != 0)
delete_host_comment(hst->flapping_comment_id);
hst->flapping_comment_id = 0;
/* clear the flapping indicator */
hst->is_flapping = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
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);
/* 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;
return;
}
/******************************************************************/
/***************** FLAP DETECTION STATUS FUNCTIONS ****************/
/******************************************************************/
/* enables flap detection on a program wide basis */
void enable_flap_detection_routines(void) {
host *temp_host = NULL;
service *temp_service = NULL;
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "enable_flap_detection_routines()\n");
/* bail out if we're already set */
if(enable_flap_detection == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* set flap detection flag */
enable_flap_detection = 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 program status */
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);
return;
}
/* disables flap detection on a program wide basis */
void disable_flap_detection_routines(void) {
host *temp_host = NULL;
service *temp_service = NULL;
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "disable_flap_detection_routines()\n");
/* bail out if we're already set */
if(enable_flap_detection == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* set flap detection flag */
enable_flap_detection = 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 program status */
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);
return;
}
/* enables flap detection for a specific host */
void enable_host_flap_detection(host *hst) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "enable_host_flap_detection()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Enabling flap detection for host '%s'.\n", hst->name);
/* nothing to do... */
if(hst->flap_detection_enabled == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the flap detection enabled flag */
hst->flap_detection_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* check for flapping */
check_for_host_flapping(hst, FALSE, FALSE, TRUE);
/* update host status */
update_host_status(hst, FALSE);
return;
}
/* disables flap detection for a specific host */
void disable_host_flap_detection(host *hst) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "disable_host_flap_detection()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Disabling flap detection for host '%s'.\n", hst->name);
/* nothing to do... */
if(hst->flap_detection_enabled == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the flap detection enabled flag */
hst->flap_detection_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* handle the details... */
handle_host_flap_detection_disabled(hst);
return;
}
/* handles the details for a host when flap detection is disabled (globally or per-host) */
void handle_host_flap_detection_disabled(host *hst) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_host_flap_detection_disabled()\n");
if(hst == NULL)
return;
/* if the host was flapping, remove the flapping indicator */
if(hst->is_flapping == TRUE) {
hst->is_flapping = FALSE;
/* delete the original comment we added earlier */
if(hst->flapping_comment_id != 0)
delete_host_comment(hst->flapping_comment_id);
hst->flapping_comment_id = 0;
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "HOST FLAPPING ALERT: %s;DISABLED; Flap detection has been disabled\n", hst->name);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_DISABLED, HOST_FLAPPING, hst, hst->percent_state_change, 0.0, 0.0, NULL);
#endif
/* send a notification */
host_notification(hst, NOTIFICATION_FLAPPINGDISABLED, 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;
}
/* update host status */
update_host_status(hst, FALSE);
return;
}
/* enables flap detection for a specific service */
void enable_service_flap_detection(service *svc) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "enable_service_flap_detection()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Enabling flap detection for service '%s' on host '%s'.\n", svc->description, svc->host_name);
/* nothing to do... */
if(svc->flap_detection_enabled == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the flap detection enabled flag */
svc->flap_detection_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* check for flapping */
check_for_service_flapping(svc, FALSE, TRUE);
/* update service status */
update_service_status(svc, FALSE);
return;
}
/* disables flap detection for a specific service */
void disable_service_flap_detection(service *svc) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "disable_service_flap_detection()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Disabling flap detection for service '%s' on host '%s'.\n", svc->description, svc->host_name);
/* nothing to do... */
if(svc->flap_detection_enabled == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the flap detection enabled flag */
svc->flap_detection_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* handle the details... */
handle_service_flap_detection_disabled(svc);
return;
}
/* handles the details for a service when flap detection is disabled (globally or per-service) */
void handle_service_flap_detection_disabled(service *svc) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_service_flap_detection_disabled()\n");
if(svc == NULL)
return;
/* if the service was flapping, remove the flapping indicator */
if(svc->is_flapping == TRUE) {
svc->is_flapping = FALSE;
/* delete the original comment we added earlier */
if(svc->flapping_comment_id != 0)
delete_service_comment(svc->flapping_comment_id);
svc->flapping_comment_id = 0;
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE FLAPPING ALERT: %s;%s;DISABLED; Flap detection has been disabled\n", svc->host_name, svc->description);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_DISABLED, SERVICE_FLAPPING, svc, svc->percent_state_change, 0.0, 0.0, NULL);
#endif
/* send a notification */
service_notification(svc, NOTIFICATION_FLAPPINGDISABLED, 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;
}
/* update service status */
update_service_status(svc, FALSE);
return;
}
nagios/base/logging.c 0000664 0000000 0000000 00000035507 12210155146 0015051 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* LOGGING.C - Log file functions for use with Nagios
*
* Copyright (c) 1999-2007 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 10-28-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.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/statusdata.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/broker.h"
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 */
}
/******************************************************************/
/************************ LOGGING FUNCTIONS ***********************/
/******************************************************************/
/* write something to the console */
static void write_to_console(char *buffer) {
/* should we print to the console? */
if(daemon_mode == FALSE)
printf("%s\n", buffer);
}
/* write something to the log file, syslog, and possibly the console */
static void write_to_logs_and_console(char *buffer, unsigned long data_type, int display) {
register int len = 0;
register int x = 0;
/* strip unnecessary newlines */
len = strlen(buffer);
for(x = len - 1; x >= 0; x--) {
if(buffer[x] == '\n')
buffer[x] = '\x0';
else
break;
}
/* write messages to the logs */
write_to_all_logs(buffer, data_type);
/* write message to the console */
if(display == TRUE) {
/* don't display warnings if we're just testing scheduling */
if(test_scheduling == TRUE && data_type == NSLOG_VERIFICATION_WARNING)
return;
write_to_console(buffer);
}
}
/* The main logging function */
void logit(int data_type, int display, const char *fmt, ...) {
va_list ap;
char *buffer = NULL;
va_start(ap, fmt);
if(vasprintf(&buffer, fmt, ap) > 0) {
write_to_logs_and_console(buffer, data_type, display);
free(buffer);
}
va_end(ap);
}
/* write something to the log file and syslog facility */
int write_to_all_logs(char *buffer, unsigned long data_type) {
/* write to syslog */
write_to_syslog(buffer, data_type);
/* write to main log */
write_to_log(buffer, data_type, NULL);
return OK;
}
/* write something to the log file and syslog facility */
static void write_to_all_logs_with_timestamp(char *buffer, unsigned long data_type, time_t *timestamp) {
/* write to syslog */
write_to_syslog(buffer, data_type);
/* write to main log */
write_to_log(buffer, data_type, timestamp);
}
/* write something to the nagios log file */
int write_to_log(char *buffer, unsigned long data_type, time_t *timestamp) {
FILE *fp = NULL;
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)
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);
return ERROR;
}
/* what timestamp should we use? */
if(timestamp == NULL)
time(&log_time);
else
log_time = *timestamp;
/* strip any newlines from the end of the buffer */
strip(buffer);
/* write the buffer to the log file */
fprintf(fp, "[%lu] %s\n", log_time, buffer);
fclose(fp);
#ifdef USE_EVENT_BROKER
/* send data to the event broker */
broker_log_data(NEBTYPE_LOG_DATA, NEBFLAG_NONE, NEBATTR_NONE, buffer, data_type, log_time, NULL);
#endif
return OK;
}
/* write something to the syslog facility */
int write_to_syslog(char *buffer, unsigned long data_type) {
if(buffer == NULL)
return ERROR;
/* don't log anything if we're not actually running... */
if(verify_config == TRUE || test_scheduling == TRUE)
return OK;
/* bail out if we shouldn't write to syslog */
if(use_syslog == FALSE)
return OK;
/* make sure we should log this type of entry */
if(!(data_type & syslog_options))
return OK;
/* write the buffer to the syslog facility */
syslog(LOG_USER | LOG_INFO, "%s", buffer);
return OK;
}
/* write a service problem/recovery to the nagios log file */
int log_service_event(service *svc) {
char *temp_buffer = NULL;
unsigned long log_options = 0L;
host *temp_host = NULL;
/* don't log soft errors if the user doesn't want to */
if(svc->state_type == SOFT_STATE && !log_service_retries)
return OK;
/* get the log options */
if(svc->current_state == STATE_UNKNOWN)
log_options = NSLOG_SERVICE_UNKNOWN;
else if(svc->current_state == STATE_WARNING)
log_options = NSLOG_SERVICE_WARNING;
else if(svc->current_state == STATE_CRITICAL)
log_options = NSLOG_SERVICE_CRITICAL;
else
log_options = NSLOG_SERVICE_OK;
/* find the associated host */
if((temp_host = svc->host_ptr) == NULL)
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);
write_to_all_logs(temp_buffer, log_options);
return OK;
}
/* write a host problem/recovery to the log file */
int log_host_event(host *hst) {
char *temp_buffer = NULL;
unsigned long log_options = 0L;
/* get the log options */
if(hst->current_state == HOST_DOWN)
log_options = NSLOG_HOST_DOWN;
else if(hst->current_state == HOST_UNREACHABLE)
log_options = NSLOG_HOST_UNREACHABLE;
else
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);
write_to_all_logs(temp_buffer, log_options);
my_free(temp_buffer);
return OK;
}
/* logs host states */
int log_host_states(int type, time_t *timestamp) {
char *temp_buffer = NULL;
host *temp_host = NULL;;
/* bail if we shouldn't be logging initial states */
if(type == INITIAL_STATES && log_initial_states == FALSE)
return OK;
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);
write_to_all_logs_with_timestamp(temp_buffer, NSLOG_INFO_MESSAGE, timestamp);
my_free(temp_buffer);
}
return OK;
}
/* logs service states */
int log_service_states(int type, time_t *timestamp) {
char *temp_buffer = NULL;
service *temp_service = NULL;
host *temp_host = NULL;;
/* bail if we shouldn't be logging initial states */
if(type == INITIAL_STATES && log_initial_states == FALSE)
return OK;
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
/* find the associated host */
if((temp_host = temp_service->host_ptr) == NULL)
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);
write_to_all_logs_with_timestamp(temp_buffer, NSLOG_INFO_MESSAGE, timestamp);
my_free(temp_buffer);
}
return OK;
}
/* rotates the main log file */
int rotate_log_file(time_t rotation_time) {
char *temp_buffer = NULL;
char method_string[16] = "";
char *log_archive = NULL;
struct tm *t, tm_s;
int rename_result = 0;
int stat_result = -1;
struct stat log_file_stat;
if(log_rotation_method == LOG_ROTATION_NONE) {
return OK;
}
else if(log_rotation_method == LOG_ROTATION_HOURLY)
strcpy(method_string, "HOURLY");
else if(log_rotation_method == LOG_ROTATION_DAILY)
strcpy(method_string, "DAILY");
else if(log_rotation_method == LOG_ROTATION_WEEKLY)
strcpy(method_string, "WEEKLY");
else if(log_rotation_method == LOG_ROTATION_MONTHLY)
strcpy(method_string, "MONTHLY");
else
return ERROR;
/* update the last log rotation time and status log */
last_log_rotation = time(NULL);
update_program_status(FALSE);
t = localtime_r(&rotation_time, &tm_s);
stat_result = stat(log_file, &log_file_stat);
/* 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);
/* rotate the log file */
rename_result = my_rename(log_file, log_archive);
if(rename_result) {
my_free(log_archive);
return ERROR;
}
/* record the log rotation after it has been done... */
asprintf(&temp_buffer, "LOG ROTATION: %s\n", method_string);
write_to_all_logs_with_timestamp(temp_buffer, NSLOG_PROCESS_INFO, &rotation_time);
my_free(temp_buffer);
/* record log file version format */
write_log_file_info(&rotation_time);
if(stat_result == 0) {
chmod(log_file, log_file_stat.st_mode);
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);
/* free memory */
my_free(log_archive);
return OK;
}
/* record log file version/info */
int write_log_file_info(time_t *timestamp) {
char *temp_buffer = NULL;
/* write log version */
asprintf(&temp_buffer, "LOG VERSION: %s\n", LOG_VERSION_2);
write_to_all_logs_with_timestamp(temp_buffer, NSLOG_PROCESS_INFO, timestamp);
my_free(temp_buffer);
return OK;
}
/* opens the debug log for writing */
int open_debug_log(void) {
/* 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((debug_file_fp = fopen(debug_file, "a+")) == NULL)
return ERROR;
return OK;
}
/* 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;
}
return OK;
}
/* closes the debug log */
int close_debug_log(void) {
if(debug_file_fp != NULL)
fclose(debug_file_fp);
debug_file_fp = NULL;
return OK;
}
/* write to the debug log */
int log_debug_info(int level, int verbosity, const char *fmt, ...) {
va_list ap;
char *temp_path = NULL;
struct timeval current_time;
if(!(debug_level == DEBUGL_ALL || (level & debug_level)))
return OK;
if(verbosity > debug_verbosity)
return OK;
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());
/* write the data */
va_start(ap, fmt);
vfprintf(debug_file_fp, fmt, ap);
va_end(ap);
/* flush, so we don't have problems tailing or when fork()ing */
fflush(debug_file_fp);
/* if file has grown beyond max, rotate it */
if((unsigned long)ftell(debug_file_fp) > max_debug_file_size && max_debug_file_size > 0L) {
/* close the file */
close_debug_log();
/* rotate the log file */
asprintf(&temp_path, "%s.old", debug_file);
if(temp_path) {
/* unlink the old debug file */
unlink(temp_path);
/* rotate the debug file */
my_rename(debug_file, temp_path);
/* free memory */
my_free(temp_path);
}
/* open a new file */
open_debug_log();
}
pthread_mutex_unlock(&debug_fp_lock);
return OK;
}
nagios/base/nagios.c 0000664 0000000 0000000 00000077600 12210155146 0014703 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* 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:
*
* Nagios is a network monitoring tool that will check hosts and services
* that you specify. It has the ability to notify contacts via email, pager,
* or other user-defined methods when a service or host goes down and
* recovers. Service and host monitoring is done through the use of external
* plugins which can be developed independently of Nagios.
*
* 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/comments.h"
#include "../include/downtime.h"
#include "../include/statusdata.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/sretention.h"
#include "../include/perfdata.h"
#include "../include/broker.h"
#include "../include/nebmods.h"
#include "../include/nebmodules.h"
/*#define DEBUG_MEMORY 1*/
#ifdef DEBUG_MEMORY
#include
#endif
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;
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 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;
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 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;
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;
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 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 result;
int error = FALSE;
char *buffer = NULL;
int display_license = FALSE;
int display_help = FALSE;
int c = 0;
struct tm *tm, tm_s;
time_t now;
char datestring[256];
nagios_macros *mac;
mac = get_global_macros();
#ifdef HAVE_GETOPT_H
int option_index = 0;
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"license", no_argument, 0, 'V'},
{"verify-config", no_argument, 0, 'v'},
{"daemon", no_argument, 0, 'd'},
{"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'},
{0, 0, 0, 0}
};
#endif
/* 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
if(c == -1 || c == EOF)
break;
switch(c) {
case '?': /* usage */
case 'h':
display_help = TRUE;
break;
case 'V': /* version */
display_license = TRUE;
break;
case 'v': /* verify */
verify_config = TRUE;
break;
case 's': /* scheduling check */
test_scheduling = TRUE;
break;
case 'd': /* daemon mode */
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;
case 'u': /* use precached object config */
use_precached_objects = TRUE;
break;
default:
break;
}
}
/* 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(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) 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");
}
/* just display the license */
if(display_license == TRUE) {
printf("This program is free software; you can redistribute it and/or modify\n");
printf("it under the terms of the GNU General Public License version 2 as\n");
printf("published by the Free Software Foundation.\n\n");
printf("This program is distributed in the hope that it will be useful,\n");
printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
printf("GNU General Public License for more details.\n\n");
printf("You should have received a copy of the GNU General Public License\n");
printf("along with this program; if not, write to the Free Software\n");
printf("Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
exit(OK);
}
/* make sure we got the main config file on the command line... */
if(optind >= argc)
error = TRUE;
/* if there are no command line options (or if we encountered an error), print usage */
if(error == TRUE || display_help == TRUE) {
printf("Usage: %s [options] \n", argv[0]);
printf("\n");
printf("Options:\n");
printf("\n");
printf(" -v, --verify-config Verify all configuration data\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(" -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("\n");
printf("Visit the Nagios website at http://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");
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]);
if(config_file == NULL) {
printf("Error allocating memory.\n");
exit(ERROR);
}
/* make sure the config file uses an absolute path */
if(config_file[0] != '/') {
/* save the name of the config file */
buffer = (char *)strdup(config_file);
/* 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);
}
/* 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) {
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");
}
}
else
printf(" Error processing main config file!\n\n");
printf("\n");
/* there was a problem reading the config files */
if(result != OK) {
/* 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("\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(" 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");
}
/* the config files were okay, so run the pre-flight check */
else {
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();
/* free config_file */
my_free(config_file);
/* exit */
exit(result);
}
/* we're just testing scheduling... */
else if(test_scheduling == TRUE) {
/* 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) {
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) {
/* initialize the event timing loop */
init_timing_loop();
/* 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
/* clean up after ourselves */
cleanup();
/* exit */
exit(result);
}
/* else start to monitor things... */
else {
/* keep monitoring things until we get a shutdown command */
do {
/* reset program variables */
reset_variables();
/* get PID */
nagios_pid = (int)getpid();
/* read in the configuration files (main and resource config files) */
result = read_main_config_file(config_file);
/* 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();
/* drop privileges */
if(drop_privileges(nagios_user, nagios_group) == ERROR) {
logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR | NSLOG_CONFIG_ERROR, TRUE, "Failed to drop privileges. Aborting.");
cleanup();
exit(ERROR);
}
#ifdef USE_EVENT_BROKER
/* initialize modules */
neb_init_modules();
neb_init_callback_list();
#endif
/* 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());
/* log the local time - may be different than clock time due to timezone offset */
now = time(NULL);
tm = localtime_r(&now, &tm_s);
strftime(datestring, sizeof(datestring), "%a %b %d %H:%M:%S %Z %Y", tm);
logit(NSLOG_PROCESS_INFO, TRUE, "Local time is %s", datestring);
/* write log version/info */
write_log_file_info(NULL);
#ifdef USE_EVENT_BROKER
/* load modules */
neb_load_all_modules();
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_PRELAUNCH, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
/* read in all object config data */
if(result == OK)
result = read_all_object_data(config_file);
/* there was a problem reading the config files */
if(result != OK)
logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR | NSLOG_CONFIG_ERROR, TRUE, "Bailing out due to one or more errors encountered in the configuration files. Run Nagios from the command line with the -v option to verify your config before restarting. (PID=%d)", (int)getpid());
else {
/* run the pre-flight check to make sure everything looks okay*/
if((result = pre_flight_check()) != OK)
logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR | NSLOG_VERIFICATION_ERROR, TRUE, "Bailing out due to errors encountered while running the pre-flight check. Run Nagios from the command line with the -v option to verify your config before restarting. (PID=%d)\n", (int)getpid());
}
/* an error occurred that prevented us from (re)starting */
if(result != OK) {
/* if we were restarting, we need to cleanup from the previous run */
if(sigrestart == TRUE) {
/* clean up the status data */
cleanup_status_data(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();
}
#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 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();
#ifdef USE_EVENT_BROKER
/* send program data to broker */
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)
initialize_status_data(config_file);
/* read initial service and host state information */
initialize_retention_data(config_file);
read_initial_state_information();
/* initialize comment data */
initialize_comment_data(config_file);
/* initialize scheduled downtime data */
initialize_downtime_data(config_file);
/* 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);
/* initialize the event timing loop */
init_timing_loop();
/* initialize check statistics */
init_check_stats();
/* check for updates */
check_for_nagios_updates(FALSE, TRUE);
/* update all status data (with retained information) */
update_all_status_data();
/* log initial host and service state */
log_host_states(INITIAL_STATES, NULL);
log_service_states(INITIAL_STATES, NULL);
/* reset the restart flag */
sigrestart = FALSE;
#ifdef USE_EVENT_BROKER
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_EVENTLOOPSTART, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
/* 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);
/***** start monitoring all services *****/
/* (doesn't return until a restart or shutdown signal is encountered) */
event_execution_loop();
/* 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]);
write_to_all_logs(buffer, NSLOG_PROCESS_INFO);
my_free(buffer);
}
#ifdef USE_EVENT_BROKER
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_EVENTLOOPEND, NEBFLAG_NONE, NEBATTR_NONE, NULL);
if(sigshutdown == TRUE)
broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_USER_INITIATED, NEBATTR_SHUTDOWN_NORMAL, NULL);
else if(sigrestart == TRUE)
broker_program_state(NEBTYPE_PROCESS_RESTART, NEBFLAG_USER_INITIATED, NEBATTR_RESTART_NORMAL, NULL);
#endif
/* save service and host state information */
save_state_information(FALSE);
cleanup_retention_data(config_file);
/* clean up performance data */
cleanup_performance_data(config_file);
/* clean up the scheduled downtime data */
cleanup_downtime_data(config_file);
/* clean up the comment data */
cleanup_comment_data(config_file);
/* 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 embedded perl interpreter */
if(sigrestart == FALSE)
deinit_embedded_perl();
/* 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);
/* log a shutdown message */
logit(NSLOG_PROCESS_INFO, TRUE, "Successfully shutdown... (PID=%d)\n", (int)getpid());
}
/* clean up after ourselves */
cleanup();
/* close debug log */
close_debug_log();
}
while(sigrestart == TRUE && sigshutdown == FALSE);
/* free misc memory */
my_free(config_file);
}
return OK;
}
nagios/base/nagiostats.c 0000664 0000000 0000000 00000225703 12210155146 0015576 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* 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:
*
* 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/nagios.h"
#include "../include/locations.h"
#define STATUS_NO_DATA 0
#define STATUS_INFO_DATA 1
#define STATUS_PROGRAM_DATA 2
#define STATUS_HOST_DATA 3
#define STATUS_SERVICE_DATA 4
char *main_config_file = NULL;
char *status_file = NULL;
char *nagiostats_file = NULL;
char *mrtg_variables = NULL;
char *mrtg_delimiter = "\n";
int mrtg_mode = FALSE;
time_t status_creation_date = 0L;
char *status_version = NULL;
time_t program_start = 0L;
int status_service_entries = 0;
int status_host_entries = 0;
unsigned long nagios_pid = 0L;
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;
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;
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;
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;
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;
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;
int external_commands_last_1min = 0;
int external_commands_last_5min = 0;
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);
int main(int argc, char **argv) {
int result;
int error = FALSE;
int display_license = FALSE;
int display_help = FALSE;
int c;
#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}
};
#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;
switch(c) {
case '?':
case 'h':
display_help = TRUE;
break;
case 'V':
display_license = TRUE;
break;
case 'L':
display_license = TRUE;
break;
case 'c':
if(main_config_file)
free(main_config_file);
main_config_file = strdup(optarg);
break;
case 's':
nagiostats_file = strdup(optarg);
break;
case 'm':
mrtg_mode = TRUE;
break;
case 'd':
mrtg_variables = strdup(optarg);
break;
case 'D':
mrtg_delimiter = strdup(optarg);
break;
default:
break;
}
}
if(mrtg_mode == FALSE) {
printf("\nNagios Stats %s\n", PROGRAM_VERSION);
printf("Copyright (c) 2003-2008 Ethan Galstad (www.nagios.org)\n");
printf("Last Modified: %s\n", PROGRAM_MODIFICATION_DATE);
printf("License: GPL\n\n");
}
/* just display the license */
if(display_license == TRUE) {
printf("This program is free software; you can redistribute it and/or modify\n");
printf("it under the terms of the GNU General Public License version 2 as\n");
printf("published by the Free Software Foundation.\n\n");
printf("This program is distributed in the hope that it will be useful,\n");
printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
printf("GNU General Public License for more details.\n\n");
printf("You should have received a copy of the GNU General Public License\n");
printf("along with this program; if not, write to the Free Software\n");
printf("Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
exit(OK);
}
/* if there are no command line options (or if we encountered an error), print usage */
if(error == TRUE || display_help == TRUE) {
printf("Usage: %s [options]\n", argv[0]);
printf("\n");
printf("Startup:\n");
printf(" -V, --version display program version information and exit.\n");
printf(" -L, --license display license information and exit.\n");
printf(" -h, --help display usage information and exit.\n");
printf("\n");
printf("Input file:\n");
printf(" -c, --config=FILE specifies location of main Nagios config file.\n");
printf(" -s, --statsfile=FILE specifies alternate location of file to read Nagios\n");
printf(" performance data from.\n");
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(" (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");
printf(" Defaults to a newline.\n");
printf("\n");
printf("MRTG DATA VARIABLES (-d option):\n");
printf(" PROGRUNTIME string with time Nagios process has been running.\n");
printf(" PROGRUNTIMETT time Nagios process has been running (time_t format).\n");
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(" 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");
printf(" HIGHCMDBUF highest number of external command buffer slots ever in use.\n");
printf(" NUMSERVICES total number of services.\n");
printf(" NUMHOSTS total number of hosts.\n");
printf(" NUMSVCOK number of services OK.\n");
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(" 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");
printf(" NUMSVCDOWNTIME number of services that are currently in downtime.\n");
printf(" NUMHSTUP number of hosts UP.\n");
printf(" NUMHSTDOWN number of hosts DOWN.\n");
printf(" NUMHSTUNR number of hosts UNREACHABLE.\n");
printf(" NUMHSTPROB number of host problems (DOWN or UNREACHABLE).\n");
printf(" NUMHSTCHECKED number of hosts that have been checked since start.\n");
printf(" NUMHSTSCHEDULED number of hosts that are currently scheduled to be checked.\n");
printf(" NUMHSTFLAPPING number of hosts that are currently flapping.\n");
printf(" NUMHSTDOWNTIME number of hosts that are currently in downtime.\n");
printf(" NUMHSTACTCHKxM number of hosts actively checked in last 1/5/15/60 minutes.\n");
printf(" NUMHSTPSVCHKxM number of hosts passively checked in last 1/5/15/60 minutes.\n");
printf(" NUMSVCACTCHKxM number of services actively checked in last 1/5/15/60 minutes.\n");
printf(" NUMSVCPSVCHKxM number of services passively checked in last 1/5/15/60 minutes.\n");
printf(" xxxACTSVCLAT MIN/MAX/AVG active service check latency (ms).\n");
printf(" xxxACTSVCEXT MIN/MAX/AVG active service check execution time (ms).\n");
printf(" xxxACTSVCPSC MIN/MAX/AVG active service check %% state change.\n");
printf(" xxxPSVSVCLAT MIN/MAX/AVG passive service check latency (ms).\n");
printf(" xxxPSVSVCPSC MIN/MAX/AVG passive service check %% state change.\n");
printf(" xxxSVCPSC MIN/MAX/AVG service check %% state change.\n");
printf(" xxxACTHSTLAT MIN/MAX/AVG active host check latency (ms).\n");
printf(" xxxACTHSTEXT MIN/MAX/AVG active host check execution time (ms).\n");
printf(" xxxACTHSTPSC MIN/MAX/AVG active host check %% state change.\n");
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(" NUMEXTCMDSxM number of external commands processed in last 1/5/15 minutes.\n");
printf("\n");
printf(" Note: Replace x's in MRTG variable names with 'MIN', 'MAX', 'AVG', or the\n");
printf(" the appropriate number (i.e. '1', '5', '15', or '60').\n");
printf("\n");
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 {
/* 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;
}
}
/* display stats */
if(mrtg_mode == FALSE)
display_stats();
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;
else
return OK;
}
int display_mrtg_values(void) {
char *temp_ptr;
time_t current_time;
unsigned long time_difference;
int days;
int hours;
int minutes;
int seconds;
time(¤t_time);
if(mrtg_variables == NULL)
return OK;
/* process all variables */
for(temp_ptr = strtok(mrtg_variables, ","); temp_ptr != NULL; temp_ptr = strtok(NULL, ",")) {
if(!strcmp(temp_ptr, "PROGRUNTIME")) {
time_difference = (current_time - program_start);
get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds);
printf("%dd %dh %dm %ds%s", days, hours, minutes, seconds, mrtg_delimiter);
}
else if(!strcmp(temp_ptr, "PROGRUNTIMETT")) {
time_difference = (current_time - program_start);
printf("%lu%s", time_difference, mrtg_delimiter);
}
else if(!strcmp(temp_ptr, "STATUSFILEAGE")) {
time_difference = (current_time - status_creation_date);
get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds);
printf("%dd %dh %dm %ds%s", days, hours, minutes, seconds, mrtg_delimiter);
}
else if(!strcmp(temp_ptr, "STATUSFILEAGETT")) {
time_difference = (current_time - status_creation_date);
printf("%lu%s", time_difference, mrtg_delimiter);
}
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);
else if(!strcmp(temp_ptr, "NAGIOSVERPID"))
printf("Nagios %s (pid=%lu)%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"))
printf("%d%s", status_host_entries, mrtg_delimiter);
/* active service check latency */
else if(!strcmp(temp_ptr, "MINACTSVCLAT"))
printf("%d%s", (int)(min_active_service_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTSVCLAT"))
printf("%d%s", (int)(max_active_service_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTSVCLAT"))
printf("%d%s", (int)(average_active_service_latency * 1000), mrtg_delimiter);
/* active service check execution time */
else if(!strcmp(temp_ptr, "MINACTSVCEXT"))
printf("%d%s", (int)(min_active_service_execution_time * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTSVCEXT"))
printf("%d%s", (int)(max_active_service_execution_time * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTSVCEXT"))
printf("%d%s", (int)(average_active_service_execution_time * 1000), mrtg_delimiter);
/* active service check percent state change */
else if(!strcmp(temp_ptr, "MINACTSVCPSC"))
printf("%d%s", (int)min_active_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTSVCPSC"))
printf("%d%s", (int)max_active_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTSVCPSC"))
printf("%d%s", (int)average_active_service_state_change, mrtg_delimiter);
/* passive service check latency */
else if(!strcmp(temp_ptr, "MINPSVSVCLAT"))
printf("%d%s", (int)(min_passive_service_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXPSVSVCLAT"))
printf("%d%s", (int)(max_passive_service_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGPSVSVCLAT"))
printf("%d%s", (int)(average_passive_service_latency * 1000), mrtg_delimiter);
/* passive service check percent state change */
else if(!strcmp(temp_ptr, "MINPSVSVCPSC"))
printf("%d%s", (int)min_passive_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXPSVSVCPSC"))
printf("%d%s", (int)max_passive_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGPSVSVCPSC"))
printf("%d%s", (int)average_passive_service_state_change, mrtg_delimiter);
/* service check percent state change */
else if(!strcmp(temp_ptr, "MINSVCPSC"))
printf("%d%s", (int)min_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXSVCPSC"))
printf("%d%s", (int)max_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGSVCPSC"))
printf("%d%s", (int)average_service_state_change, mrtg_delimiter);
/* active host check latency */
else if(!strcmp(temp_ptr, "MINACTHSTLAT"))
printf("%d%s", (int)(min_active_host_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTHSTLAT"))
printf("%d%s", (int)(max_active_host_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTHSTLAT"))
printf("%d%s", (int)(average_active_host_latency * 1000), mrtg_delimiter);
/* active host check execution time */
else if(!strcmp(temp_ptr, "MINACTHSTEXT"))
printf("%d%s", (int)(min_active_host_execution_time * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTHSTEXT"))
printf("%d%s", (int)(max_active_host_execution_time * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTHSTEXT"))
printf("%d%s", (int)(average_active_host_execution_time * 1000), mrtg_delimiter);
/* active host check percent state change */
else if(!strcmp(temp_ptr, "MINACTHSTPSC"))
printf("%d%s", (int)min_active_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTHSTPSC"))
printf("%d%s", (int)max_active_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTHSTPSC"))
printf("%d%s", (int)average_active_host_state_change, mrtg_delimiter);
/* passive host check latency */
else if(!strcmp(temp_ptr, "MINPSVHSTLAT"))
printf("%d%s", (int)(min_passive_host_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXPSVHSTLAT"))
printf("%d%s", (int)(max_passive_host_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGPSVHSTLAT"))
printf("%d%s", (int)(average_passive_host_latency * 1000), mrtg_delimiter);
/* passive host check percent state change */
else if(!strcmp(temp_ptr, "MINPSVHSTPSC"))
printf("%d%s", (int)min_passive_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXPSVHSTPSC"))
printf("%d%s", (int)max_passive_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGPSVHSTPSC"))
printf("%d%s", (int)average_passive_host_state_change, mrtg_delimiter);
/* host check percent state change */
else if(!strcmp(temp_ptr, "MINHSTPSC"))
printf("%d%s", (int)min_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXHSTPSC"))
printf("%d%s", (int)max_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGHSTPSC"))
printf("%d%s", (int)average_host_state_change, mrtg_delimiter);
/* active host checks over time */
else if(!strcmp(temp_ptr, "NUMHSTACTCHK1M"))
printf("%d%s", active_hosts_checked_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTACTCHK5M"))
printf("%d%s", active_hosts_checked_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTACTCHK15M"))
printf("%d%s", active_hosts_checked_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTACTCHK60M"))
printf("%d%s", active_hosts_checked_last_1hour, mrtg_delimiter);
/* passive host checks over time */
else if(!strcmp(temp_ptr, "NUMHSTPSVCHK1M"))
printf("%d%s", passive_hosts_checked_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTPSVCHK5M"))
printf("%d%s", passive_hosts_checked_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTPSVCHK15M"))
printf("%d%s", passive_hosts_checked_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTPSVCHK60M"))
printf("%d%s", passive_hosts_checked_last_1hour, mrtg_delimiter);
/* active service checks over time */
else if(!strcmp(temp_ptr, "NUMSVCACTCHK1M"))
printf("%d%s", active_services_checked_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCACTCHK5M"))
printf("%d%s", active_services_checked_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCACTCHK15M"))
printf("%d%s", active_services_checked_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCACTCHK60M"))
printf("%d%s", active_services_checked_last_1hour, mrtg_delimiter);
/* passive service checks over time */
else if(!strcmp(temp_ptr, "NUMSVCPSVCHK1M"))
printf("%d%s", passive_services_checked_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCPSVCHK5M"))
printf("%d%s", passive_services_checked_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCPSVCHK15M"))
printf("%d%s", passive_services_checked_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCPSVCHK60M"))
printf("%d%s", passive_services_checked_last_1hour, mrtg_delimiter);
/* host check statistics */
else if(!strcmp(temp_ptr, "NUMACTHSTCHECKS1M"))
printf("%d%s", active_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMACTHSTCHECKS5M"))
printf("%d%s", active_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMACTHSTCHECKS15M"))
printf("%d%s", active_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTHSTCHECKS1M"))
printf("%d%s", active_ondemand_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTHSTCHECKS5M"))
printf("%d%s", active_ondemand_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTHSTCHECKS15M"))
printf("%d%s", active_ondemand_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTHSTCHECKS1M"))
printf("%d%s", active_scheduled_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTHSTCHECKS5M"))
printf("%d%s", active_scheduled_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTHSTCHECKS15M"))
printf("%d%s", active_scheduled_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPARHSTCHECKS1M"))
printf("%d%s", parallel_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPARHSTCHECKS5M"))
printf("%d%s", parallel_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPARHSTCHECKS15M"))
printf("%d%s", parallel_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSERHSTCHECKS1M"))
printf("%d%s", serial_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSERHSTCHECKS5M"))
printf("%d%s", serial_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSERHSTCHECKS15M"))
printf("%d%s", serial_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVHSTCHECKS1M"))
printf("%d%s", passive_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVHSTCHECKS5M"))
printf("%d%s", passive_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVHSTCHECKS15M"))
printf("%d%s", passive_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDHSTCHECKS1M"))
printf("%d%s", active_cached_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDHSTCHECKS5M"))
printf("%d%s", active_cached_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDHSTCHECKS15M"))
printf("%d%s", active_cached_host_checks_last_15min, mrtg_delimiter);
/* service check statistics */
else if(!strcmp(temp_ptr, "NUMACTSVCCHECKS1M"))
printf("%d%s", active_service_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMACTSVCCHECKS5M"))
printf("%d%s", active_service_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMACTSVCCHECKS15M"))
printf("%d%s", active_service_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTSVCCHECKS1M"))
printf("%d%s", active_ondemand_service_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTSVCCHECKS5M"))
printf("%d%s", active_ondemand_service_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTSVCCHECKS15M"))
printf("%d%s", active_ondemand_service_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTSVCCHECKS1M"))
printf("%d%s", active_scheduled_service_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTSVCCHECKS5M"))
printf("%d%s", active_scheduled_service_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTSVCCHECKS15M"))
printf("%d%s", active_scheduled_service_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVSVCCHECKS1M"))
printf("%d%s", passive_service_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVSVCCHECKS5M"))
printf("%d%s", passive_service_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVSVCCHECKS15M"))
printf("%d%s", passive_service_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDSVCCHECKS1M"))
printf("%d%s", active_cached_service_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDSVCCHECKS5M"))
printf("%d%s", active_cached_service_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDSVCCHECKS15M"))
printf("%d%s", active_cached_service_checks_last_15min, mrtg_delimiter);
/* external command stats */
else if(!strcmp(temp_ptr, "NUMEXTCMDS1M"))
printf("%d%s", external_commands_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMEXTCMDS5M"))
printf("%d%s", external_commands_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMEXTCMDS15M"))
printf("%d%s", external_commands_last_15min, mrtg_delimiter);
/* service states */
else if(!strcmp(temp_ptr, "NUMSVCOK"))
printf("%d%s", services_ok, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCWARN"))
printf("%d%s", services_warning, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCUNKN"))
printf("%d%s", services_unknown, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCCRIT"))
printf("%d%s", services_critical, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCPROB"))
printf("%d%s", services_warning + services_unknown + services_critical, mrtg_delimiter);
/* misc service info */
else if(!strcmp(temp_ptr, "NUMSVCCHECKED"))
printf("%d%s", services_checked, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCSCHEDULED"))
printf("%d%s", services_scheduled, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCFLAPPING"))
printf("%d%s", services_flapping, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCDOWNTIME"))
printf("%d%s", services_in_downtime, mrtg_delimiter);
/* host states */
else if(!strcmp(temp_ptr, "NUMHSTUP"))
printf("%d%s", hosts_up, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTDOWN"))
printf("%d%s", hosts_down, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTUNR"))
printf("%d%s", hosts_unreachable, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTPROB"))
printf("%d%s", hosts_down + hosts_unreachable, mrtg_delimiter);
/* misc host info */
else if(!strcmp(temp_ptr, "NUMHSTCHECKED"))
printf("%d%s", hosts_checked, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTSCHEDULED"))
printf("%d%s", hosts_scheduled, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTFLAPPING"))
printf("%d%s", hosts_flapping, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTDOWNTIME"))
printf("%d%s", hosts_in_downtime, mrtg_delimiter);
else
printf("%s%s", temp_ptr, mrtg_delimiter);
}
/* add a newline if necessary */
if(strcmp(mrtg_delimiter, "\n"))
printf("\n");
return OK;
}
int display_stats(void) {
time_t current_time;
unsigned long time_difference;
int days;
int hours;
int minutes;
int seconds;
time(¤t_time);
printf("CURRENT STATUS DATA\n");
printf("------------------------------------------------------\n");
printf("Status File: %s\n", (nagiostats_file != NULL) ? nagiostats_file : 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);
printf("Status File Version: %s\n", status_version);
printf("\n");
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("\n");
printf("Total Services: %d\n", status_service_entries);
printf("Services Checked: %d\n", services_checked);
printf("Services Scheduled: %d\n", services_scheduled);
printf("Services Actively Checked: %d\n", active_service_checks);
printf("Services Passively Checked: %d\n", passive_service_checks);
printf("Total Service State Change: %.3f / %.3f / %.3f %%\n", min_service_state_change, max_service_state_change, average_service_state_change);
printf("Active Service Latency: %.3f / %.3f / %.3f sec\n", min_active_service_latency, max_active_service_latency, average_active_service_latency);
printf("Active Service Execution Time: %.3f / %.3f / %.3f sec\n", min_active_service_execution_time, max_active_service_execution_time, average_active_service_execution_time);
printf("Active Service State Change: %.3f / %.3f / %.3f %%\n", min_active_service_state_change, max_active_service_state_change, average_active_service_state_change);
printf("Active Services Last 1/5/15/60 min: %d / %d / %d / %d\n", active_services_checked_last_1min, active_services_checked_last_5min, active_services_checked_last_15min, active_services_checked_last_1hour);
printf("Passive Service Latency: %.3f / %.3f / %.3f sec\n", min_passive_service_latency, max_passive_service_latency, average_passive_service_latency);
printf("Passive Service State Change: %.3f / %.3f / %.3f %%\n", min_passive_service_state_change, max_passive_service_state_change, average_passive_service_state_change);
printf("Passive Services Last 1/5/15/60 min: %d / %d / %d / %d\n", passive_services_checked_last_1min, passive_services_checked_last_5min, passive_services_checked_last_15min, passive_services_checked_last_1hour);
printf("Services Ok/Warn/Unk/Crit: %d / %d / %d / %d\n", services_ok, services_warning, services_unknown, services_critical);
printf("Services Flapping: %d\n", services_flapping);
printf("Services In Downtime: %d\n", services_in_downtime);
printf("\n");
printf("Total Hosts: %d\n", status_host_entries);
printf("Hosts Checked: %d\n", hosts_checked);
printf("Hosts Scheduled: %d\n", hosts_scheduled);
printf("Hosts Actively Checked: %d\n", active_host_checks);
printf("Host Passively Checked: %d\n", passive_host_checks);
printf("Total Host State Change: %.3f / %.3f / %.3f %%\n", min_host_state_change, max_host_state_change, average_host_state_change);
printf("Active Host Latency: %.3f / %.3f / %.3f sec\n", min_active_host_latency, max_active_host_latency, average_active_host_latency);
printf("Active Host Execution Time: %.3f / %.3f / %.3f sec\n", min_active_host_execution_time, max_active_host_execution_time, average_active_host_execution_time);
printf("Active Host State Change: %.3f / %.3f / %.3f %%\n", min_active_host_state_change, max_active_host_state_change, average_active_host_state_change);
printf("Active Hosts Last 1/5/15/60 min: %d / %d / %d / %d\n", active_hosts_checked_last_1min, active_hosts_checked_last_5min, active_hosts_checked_last_15min, active_hosts_checked_last_1hour);
printf("Passive Host Latency: %.3f / %.3f / %.3f sec\n", min_passive_host_latency, max_passive_host_latency, average_passive_host_latency);
printf("Passive Host State Change: %.3f / %.3f / %.3f %%\n", min_passive_host_state_change, max_passive_host_state_change, average_passive_host_state_change);
printf("Passive Hosts Last 1/5/15/60 min: %d / %d / %d / %d\n", passive_hosts_checked_last_1min, passive_hosts_checked_last_5min, passive_hosts_checked_last_15min, passive_hosts_checked_last_1hour);
printf("Hosts Up/Down/Unreach: %d / %d / %d\n", hosts_up, hosts_down, hosts_unreachable);
printf("Hosts Flapping: %d\n", hosts_flapping);
printf("Hosts In Downtime: %d\n", hosts_in_downtime);
printf("\n");
printf("Active Host Checks Last 1/5/15 min: %d / %d / %d\n", active_host_checks_last_1min, active_host_checks_last_5min, active_host_checks_last_15min);
printf(" Scheduled: %d / %d / %d\n", active_scheduled_host_checks_last_1min, active_scheduled_host_checks_last_5min, active_scheduled_host_checks_last_15min);
printf(" On-demand: %d / %d / %d\n", active_ondemand_host_checks_last_1min, active_ondemand_host_checks_last_5min, active_ondemand_host_checks_last_15min);
printf(" Parallel: %d / %d / %d\n", parallel_host_checks_last_1min, parallel_host_checks_last_5min, parallel_host_checks_last_15min);
printf(" Serial: %d / %d / %d\n", serial_host_checks_last_1min, serial_host_checks_last_5min, serial_host_checks_last_15min);
printf(" Cached: %d / %d / %d\n", active_cached_host_checks_last_1min, active_cached_host_checks_last_5min, active_cached_host_checks_last_15min);
printf("Passive Host Checks Last 1/5/15 min: %d / %d / %d\n", passive_host_checks_last_1min, passive_host_checks_last_5min, passive_host_checks_last_15min);
printf("Active Service Checks Last 1/5/15 min: %d / %d / %d\n", active_service_checks_last_1min, active_service_checks_last_5min, active_service_checks_last_15min);
printf(" Scheduled: %d / %d / %d\n", active_scheduled_service_checks_last_1min, active_scheduled_service_checks_last_5min, active_scheduled_service_checks_last_15min);
printf(" On-demand: %d / %d / %d\n", active_ondemand_service_checks_last_1min, active_ondemand_service_checks_last_5min, active_ondemand_service_checks_last_15min);
printf(" Cached: %d / %d / %d\n", active_cached_service_checks_last_1min, active_cached_service_checks_last_5min, active_cached_service_checks_last_15min);
printf("Passive Service Checks Last 1/5/15 min: %d / %d / %d\n", passive_service_checks_last_1min, passive_service_checks_last_5min, passive_service_checks_last_15min);
printf("\n");
printf("External Commands Last 1/5/15 min: %d / %d / %d\n", external_commands_last_1min, external_commands_last_5min, external_commands_last_15min);
printf("\n");
printf("\n");
/*
printf("CURRENT COMMENT DATA\n");
printf("----------------------------------------------------\n");
printf("\n");
printf("\n");
printf("CURRENT DOWNTIME DATA\n");
printf("----------------------------------------------------\n");
printf("\n");
*/
return OK;
}
int read_config_file(void) {
char temp_buffer[MAX_INPUT_BUFFER];
FILE *fp;
char *var;
char *val;
fp = fopen(main_config_file, "r");
if(fp == NULL)
return ERROR;
/* read all lines from the main nagios config file */
while(fgets(temp_buffer, sizeof(temp_buffer) - 1, fp)) {
strip(temp_buffer);
/* skip blank lines and comments */
if(temp_buffer[0] == '#' || temp_buffer[0] == '\x0')
continue;
var = strtok(temp_buffer, "=");
val = strtok(NULL, "\n");
if(val == NULL)
continue;
if(!strcmp(var, "status_file") || !strcmp(var, "status_log") || !strcmp(var, "xsddefault_status_log")) {
if(status_file)
free(status_file);
status_file = strdup(val);
}
}
fclose(fp);
return OK;
}
int read_status_file(void) {
char temp_buffer[MAX_INPUT_BUFFER];
FILE *fp = NULL;
int data_type = STATUS_NO_DATA;
char *var = NULL;
char *val = NULL;
char *temp_ptr = NULL;
time_t current_time;
unsigned long time_difference = 0L;
double execution_time = 0.0;
double latency = 0.0;
int check_type = SERVICE_CHECK_ACTIVE;
int current_state = STATE_OK;
double state_change = 0.0;
int is_flapping = FALSE;
int downtime_depth = 0;
time_t last_check = 0L;
int should_be_scheduled = TRUE;
int has_been_checked = TRUE;
time(¤t_time);
fp = fopen(status_file, "r");
if(fp == NULL)
return ERROR;
/* read all lines in the status file */
while(fgets(temp_buffer, sizeof(temp_buffer) - 1, fp)) {
/* skip blank lines and comments */
if(temp_buffer[0] == '#' || temp_buffer[0] == '\x0')
continue;
strip(temp_buffer);
/* start of definition */
if(!strcmp(temp_buffer, "servicestatus {")) {
data_type = STATUS_SERVICE_DATA;
status_service_entries++;
}
else if(!strcmp(temp_buffer, "hoststatus {")) {
data_type = STATUS_HOST_DATA;
status_host_entries++;
}
else if(!strcmp(temp_buffer, "info {"))
data_type = STATUS_INFO_DATA;
else if(!strcmp(temp_buffer, "programstatus {"))
data_type = STATUS_PROGRAM_DATA;
/* end of definition */
else if(!strcmp(temp_buffer, "}")) {
switch(data_type) {
case STATUS_INFO_DATA:
break;
case STATUS_PROGRAM_DATA:
/* 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;
break;
case STATUS_HOST_DATA:
average_host_state_change = (((average_host_state_change * ((double)status_host_entries - 1.0)) + state_change) / (double)status_host_entries);
if(have_min_host_state_change == FALSE || min_host_state_change > state_change) {
have_min_host_state_change = TRUE;
min_host_state_change = state_change;
}
if(have_max_host_state_change == FALSE || max_host_state_change < state_change) {
have_max_host_state_change = TRUE;
max_host_state_change = state_change;
}
if(check_type == HOST_CHECK_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) {
have_min_active_host_latency = TRUE;
min_active_host_latency = latency;
}
if(have_max_active_host_latency == FALSE || max_active_host_latency < latency) {
have_max_active_host_latency = TRUE;
max_active_host_latency = latency;
}
average_active_host_execution_time = (((average_active_host_execution_time * ((double)active_host_checks - 1.0)) + execution_time) / (double)active_host_checks);
if(have_min_active_host_execution_time == FALSE || min_active_host_execution_time > execution_time) {
have_min_active_host_execution_time = TRUE;
min_active_host_execution_time = execution_time;
}
if(have_max_active_host_execution_time == FALSE || max_active_host_execution_time < execution_time) {
have_max_active_host_execution_time = TRUE;
max_active_host_execution_time = execution_time;
}
average_active_host_state_change = (((average_active_host_state_change * ((double)active_host_checks - 1.0)) + state_change) / (double)active_host_checks);
if(have_min_active_host_state_change == FALSE || min_active_host_state_change > state_change) {
have_min_active_host_state_change = TRUE;
min_active_host_state_change = state_change;
}
if(have_max_active_host_state_change == FALSE || max_active_host_state_change < state_change) {
have_max_active_host_state_change = TRUE;
max_active_host_state_change = state_change;
}
time_difference = current_time - last_check;
if(time_difference <= 3600)
active_hosts_checked_last_1hour++;
if(time_difference <= 900)
active_hosts_checked_last_15min++;
if(time_difference <= 300)
active_hosts_checked_last_5min++;
if(time_difference <= 60)
active_hosts_checked_last_1min++;
}
else {
passive_host_checks++;
average_passive_host_latency = (((average_passive_host_latency * ((double)passive_host_checks - 1.0)) + latency) / (double)passive_host_checks);
if(have_min_passive_host_latency == FALSE || min_passive_host_latency > latency) {
have_min_passive_host_latency = TRUE;
min_passive_host_latency = latency;
}
if(have_max_passive_host_latency == FALSE || max_passive_host_latency < latency) {
have_max_passive_host_latency = TRUE;
max_passive_host_latency = latency;
}
average_passive_host_state_change = (((average_passive_host_state_change * ((double)passive_host_checks - 1.0)) + state_change) / (double)passive_host_checks);
if(have_min_passive_host_state_change == FALSE || min_passive_host_state_change > state_change) {
have_min_passive_host_state_change = TRUE;
min_passive_host_state_change = state_change;
}
if(have_max_passive_host_state_change == FALSE || max_passive_host_state_change < state_change) {
have_max_passive_host_state_change = TRUE;
max_passive_host_state_change = state_change;
}
time_difference = current_time - last_check;
if(time_difference <= 3600)
passive_hosts_checked_last_1hour++;
if(time_difference <= 900)
passive_hosts_checked_last_15min++;
if(time_difference <= 300)
passive_hosts_checked_last_5min++;
if(time_difference <= 60)
passive_hosts_checked_last_1min++;
}
switch(current_state) {
case HOST_UP:
hosts_up++;
break;
case HOST_DOWN:
hosts_down++;
break;
case HOST_UNREACHABLE:
hosts_unreachable++;
break;
default:
break;
}
if(is_flapping == TRUE)
hosts_flapping++;
if(downtime_depth > 0)
hosts_in_downtime++;
if(has_been_checked == TRUE)
hosts_checked++;
if(should_be_scheduled == TRUE)
hosts_scheduled++;
break;
case STATUS_SERVICE_DATA:
average_service_state_change = (((average_service_state_change * ((double)status_service_entries - 1.0)) + state_change) / (double)status_service_entries);
if(have_min_service_state_change == FALSE || min_service_state_change > state_change) {
have_min_service_state_change = TRUE;
min_service_state_change = state_change;
}
if(have_max_service_state_change == FALSE || max_service_state_change < state_change) {
have_max_service_state_change = TRUE;
max_service_state_change = state_change;
}
if(check_type == SERVICE_CHECK_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) {
have_min_active_service_latency = TRUE;
min_active_service_latency = latency;
}
if(have_max_active_service_latency == FALSE || max_active_service_latency < latency) {
have_max_active_service_latency = TRUE;
max_active_service_latency = latency;
}
average_active_service_execution_time = (((average_active_service_execution_time * ((double)active_service_checks - 1.0)) + execution_time) / (double)active_service_checks);
if(have_min_active_service_execution_time == FALSE || min_active_service_execution_time > execution_time) {
have_min_active_service_execution_time = TRUE;
min_active_service_execution_time = execution_time;
}
if(have_max_active_service_execution_time == FALSE || max_active_service_execution_time < execution_time) {
have_max_active_service_execution_time = TRUE;
max_active_service_execution_time = execution_time;
}
average_active_service_state_change = (((average_active_service_state_change * ((double)active_service_checks - 1.0)) + state_change) / (double)active_service_checks);
if(have_min_active_service_state_change == FALSE || min_active_service_state_change > state_change) {
have_min_active_service_state_change = TRUE;
min_active_service_state_change = state_change;
}
if(have_max_active_service_state_change == FALSE || max_active_service_state_change < state_change) {
have_max_active_service_state_change = TRUE;
max_active_service_state_change = state_change;
}
time_difference = current_time - last_check;
if(time_difference <= 3600)
active_services_checked_last_1hour++;
if(time_difference <= 900)
active_services_checked_last_15min++;
if(time_difference <= 300)
active_services_checked_last_5min++;
if(time_difference <= 60)
active_services_checked_last_1min++;
}
else {
passive_service_checks++;
average_passive_service_latency = (((average_passive_service_latency * ((double)passive_service_checks - 1.0)) + latency) / (double)passive_service_checks);
if(have_min_passive_service_latency == FALSE || min_passive_service_latency > latency) {
have_min_passive_service_latency = TRUE;
min_passive_service_latency = latency;
}
if(have_max_passive_service_latency == FALSE || max_passive_service_latency < latency) {
have_max_passive_service_latency = TRUE;
max_passive_service_latency = latency;
}
average_passive_service_state_change = (((average_passive_service_state_change * ((double)passive_service_checks - 1.0)) + state_change) / (double)passive_service_checks);
if(have_min_passive_service_state_change == FALSE || min_passive_service_state_change > state_change) {
have_min_passive_service_state_change = TRUE;
min_passive_service_state_change = state_change;
}
if(have_max_passive_service_state_change == FALSE || max_passive_service_state_change < state_change) {
have_max_passive_service_state_change = TRUE;
max_passive_service_state_change = state_change;
}
time_difference = current_time - last_check;
if(time_difference <= 3600)
passive_services_checked_last_1hour++;
if(time_difference <= 900)
passive_services_checked_last_15min++;
if(time_difference <= 300)
passive_services_checked_last_5min++;
if(time_difference <= 60)
passive_services_checked_last_1min++;
}
switch(current_state) {
case STATE_OK:
services_ok++;
break;
case STATE_WARNING:
services_warning++;
break;
case STATE_UNKNOWN:
services_unknown++;
break;
case STATE_CRITICAL:
services_critical++;
break;
default:
break;
}
if(is_flapping == TRUE)
services_flapping++;
if(downtime_depth > 0)
services_in_downtime++;
if(has_been_checked == TRUE)
services_checked++;
if(should_be_scheduled == TRUE)
services_scheduled++;
break;
default:
break;
}
data_type = STATUS_NO_DATA;
execution_time = 0.0;
latency = 0.0;
check_type = 0;
current_state = 0;
state_change = 0.0;
is_flapping = FALSE;
downtime_depth = 0;
last_check = (time_t)0;
has_been_checked = FALSE;
should_be_scheduled = FALSE;
}
/* inside definition */
else if(data_type != STATUS_NO_DATA) {
var = strtok(temp_buffer, "=");
val = strtok(NULL, "\n");
if(val == NULL)
continue;
switch(data_type) {
case STATUS_INFO_DATA:
if(!strcmp(var, "created"))
status_creation_date = strtoul(val, NULL, 10);
else if(!strcmp(var, "version"))
status_version = strdup(val);
break;
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")) {
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);
}
break;
case STATUS_HOST_DATA:
if(!strcmp(var, "check_execution_time"))
execution_time = strtod(val, NULL);
else if(!strcmp(var, "check_latency"))
latency = strtod(val, NULL);
else if(!strcmp(var, "percent_state_change"))
state_change = strtod(val, NULL);
else if(!strcmp(var, "check_type"))
check_type = atoi(val);
else if(!strcmp(var, "current_state"))
current_state = atoi(val);
else if(!strcmp(var, "is_flapping"))
is_flapping = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "scheduled_downtime_depth"))
downtime_depth = atoi(val);
else if(!strcmp(var, "last_check"))
last_check = strtoul(val, NULL, 10);
else if(!strcmp(var, "has_been_checked"))
has_been_checked = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "should_be_scheduled"))
should_be_scheduled = (atoi(val) > 0) ? TRUE : FALSE;
break;
case STATUS_SERVICE_DATA:
if(!strcmp(var, "check_execution_time"))
execution_time = strtod(val, NULL);
else if(!strcmp(var, "check_latency"))
latency = strtod(val, NULL);
else if(!strcmp(var, "percent_state_change"))
state_change = strtod(val, NULL);
else if(!strcmp(var, "check_type"))
check_type = atoi(val);
else if(!strcmp(var, "current_state"))
current_state = atoi(val);
else if(!strcmp(var, "is_flapping"))
is_flapping = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "scheduled_downtime_depth"))
downtime_depth = atoi(val);
else if(!strcmp(var, "last_check"))
last_check = strtoul(val, NULL, 10);
else if(!strcmp(var, "has_been_checked"))
has_been_checked = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "should_be_scheduled"))
should_be_scheduled = (atoi(val) > 0) ? TRUE : FALSE;
break;
default:
break;
}
}
}
fclose(fp);
return OK;
}
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;
register int y;
register int z;
if(buffer == NULL || buffer[0] == '\x0')
return;
/* strip end of string */
y = (int)strlen(buffer);
for(x = y - 1; x >= 0; x--) {
if(buffer[x] == ' ' || buffer[x] == '\n' || buffer[x] == '\r' || buffer[x] == '\t' || buffer[x] == 13)
buffer[x] = '\x0';
else
break;
}
/* strip beginning of string (by shifting) */
y = (int)strlen(buffer);
for(x = 0; x < y; x++) {
if(buffer[x] == ' ' || buffer[x] == '\n' || buffer[x] == '\r' || buffer[x] == '\t' || buffer[x] == 13)
continue;
else
break;
}
if(x > 0) {
for(z = x; z < y; z++)
buffer[z - x] = buffer[z];
buffer[y - x] = '\x0';
}
return;
}
/* get days, hours, minutes, and seconds from a raw time_t format or total seconds */
void get_time_breakdown(unsigned long raw_time, int *days, int *hours, int *minutes, int *seconds) {
unsigned long temp_time;
int temp_days;
int temp_hours;
int temp_minutes;
int temp_seconds;
temp_time = raw_time;
temp_days = temp_time / 86400;
temp_time -= (temp_days * 86400);
temp_hours = temp_time / 3600;
temp_time -= (temp_hours * 3600);
temp_minutes = temp_time / 60;
temp_time -= (temp_minutes * 60);
temp_seconds = (int)temp_time;
*days = temp_days;
*hours = temp_hours;
*minutes = temp_minutes;
*seconds = temp_seconds;
return;
}
nagios/base/nebmods.c 0000664 0000000 0000000 00000047161 12210155146 0015051 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* NEBMODS.C - Event Broker Module Functions
*
* Copyright (c) 2002-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 11-02-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.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/nebmods.h"
#include "../include/neberrors.h"
#include "../include/nagios.h"
#ifdef USE_EVENT_BROKER
nebmodule *neb_module_list = NULL;
nebcallback **neb_callback_list = NULL;
extern char *temp_path;
/*#define DEBUG*/
/****************************************************************************/
/****************************************************************************/
/* INITIALIZATION/CLEANUP FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* 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)
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)
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;
int x = OK;
if(filename == NULL)
return ERROR;
/* allocate memory */
new_module = (nebmodule *)malloc(sizeof(nebmodule));
if(new_module == NULL)
return ERROR;
/* initialize vars */
new_module->filename = (char *)strdup(filename);
new_module->args = (args == NULL) ? NULL : (char *)strdup(args);
new_module->should_be_loaded = should_be_loaded;
new_module->is_currently_loaded = FALSE;
for(x = 0; x < NEBMODULE_MODINFO_NUMITEMS; x++)
new_module->info[x] = NULL;
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;
neb_module_list = new_module;
log_debug_info(DEBUGL_EVENTBROKER, 0, "Added module: name='%s', args='%s', should_be_loaded='%d'\n", filename, args, should_be_loaded);
return OK;
}
/* 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;) {
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]);
my_free(temp_module);
temp_module = next_module;
}
neb_module_list = NULL;
return OK;
}
/****************************************************************************/
/****************************************************************************/
/* LOAD/UNLOAD FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* load all modules */
int neb_load_all_modules(void) {
nebmodule *temp_module = NULL;
int result = OK;
for(temp_module = neb_module_list; temp_module; temp_module = temp_module->next) {
result = neb_load_module(temp_module);
}
return 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;
if(mod == NULL || mod->filename == NULL)
return ERROR;
/* don't reopen the module */
if(mod->is_currently_loaded == TRUE)
return OK;
/* don't load modules unless they should be loaded */
if(mod->should_be_loaded == FALSE)
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
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
return ERROR;
}
/* 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);
neb_unload_module(mod, NEBMODULE_FORCE_UNLOAD, NEBMODULE_ERROR_API_VERSION);
return ERROR;
}
/* 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
/* 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);
neb_unload_module(mod, NEBMODULE_FORCE_UNLOAD, NEBMODULE_ERROR_NO_INIT);
return ERROR;
}
/* run the module's init function */
initfunc = mod->init_func;
result = (*initfunc)(NEBMODULE_NORMAL_LOAD, mod->args, mod->module_handle);
/* 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);
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);
/* 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
log_debug_info(DEBUGL_EVENTBROKER, 0, "Module '%s' loaded with return code of '%d'\n", mod->filename, result);
if(mod->deinit_func != NULL)
log_debug_info(DEBUGL_EVENTBROKER, 0, "nebmodule_deinit() found\n");
return OK;
}
/* close (unload) all modules that are currently loaded */
int neb_unload_all_modules(int flags, int reason) {
nebmodule *temp_module;
for(temp_module = neb_module_list; temp_module; temp_module = temp_module->next) {
/* skip modules that are not loaded */
if(temp_module->is_currently_loaded == FALSE)
continue;
/* skip modules that do not have a valid handle */
if(temp_module->module_handle == NULL)
continue;
/* close/unload the module */
neb_unload_module(temp_module, flags, reason);
}
return OK;
}
/* close (unload) a particular module */
int neb_unload_module(nebmodule *mod, int flags, int reason) {
int (*deinitfunc)(int, int);
int result = OK;
if(mod == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTBROKER, 0, "Attempting to unload module '%s': flags=%d, reason=%d\n", mod->filename, flags, reason);
/* call the de-initialization function if available (and the module was initialized) */
if(mod->deinit_func && reason != NEBMODULE_ERROR_BAD_INIT) {
deinitfunc = mod->deinit_func;
/* module can opt to not be unloaded */
result = (*deinitfunc)(flags, reason);
/* if module doesn't want to be unloaded, exit with error (unless its being forced) */
if(result != OK && !(flags & NEBMODULE_FORCE_UNLOAD))
return ERROR;
}
/* 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
/* mark the module as being unloaded */
mod->is_currently_loaded = FALSE;
log_debug_info(DEBUGL_EVENTBROKER, 0, "Module '%s' unloaded successfully.\n", mod->filename);
logit(NSLOG_INFO_MESSAGE, FALSE, "Event broker module '%s' deinitialized successfully.\n", mod->filename);
return OK;
}
/****************************************************************************/
/****************************************************************************/
/* INFO FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* sets module information */
int neb_set_module_info(void *handle, int type, char *data) {
nebmodule *temp_module = NULL;
if(handle == NULL)
return NEBERROR_NOMODULE;
/* check type */
if(type < 0 || type >= NEBMODULE_MODINFO_NUMITEMS)
return NEBERROR_MODINFOBOUNDS;
/* 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)
break;
}
if(temp_module == NULL)
return NEBERROR_BADMODULEHANDLE;
/* free any previously allocated memory */
my_free(temp_module->info[type]);
/* allocate memory for the new data */
if((temp_module->info[type] = (char *)strdup(data)) == NULL)
return NEBERROR_NOMEM;
return OK;
}
/****************************************************************************/
/****************************************************************************/
/* CALLBACK FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* allows a module to register a callback function */
int neb_register_callback(int callback_type, void *mod_handle, int priority, int (*callback_func)(int, void *)) {
nebmodule *temp_module = NULL;
nebcallback *new_callback = NULL;
nebcallback *temp_callback = NULL;
nebcallback *last_callback = NULL;
if(callback_func == NULL)
return NEBERROR_NOCALLBACKFUNC;
if(neb_callback_list == NULL)
return NEBERROR_NOCALLBACKLIST;
if(mod_handle == NULL)
return NEBERROR_NOMODULEHANDLE;
/* make sure the callback type is within bounds */
if(callback_type < 0 || callback_type >= NEBCALLBACK_NUMITEMS)
return NEBERROR_CALLBACKBOUNDS;
/* 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)
break;
}
if(temp_module == NULL)
return NEBERROR_BADMODULEHANDLE;
/* allocate memory */
new_callback = (nebcallback *)malloc(sizeof(nebcallback));
if(new_callback == NULL)
return NEBERROR_NOMEM;
new_callback->priority = priority;
new_callback->module_handle = (void *)mod_handle;
new_callback->callback_func = (void *)callback_func;
/* add new function to callback list, sorted by priority (first come, first served for same priority) */
new_callback->next = NULL;
if(neb_callback_list[callback_type] == NULL)
neb_callback_list[callback_type] = new_callback;
else {
last_callback = NULL;
for(temp_callback = neb_callback_list[callback_type]; temp_callback != NULL; temp_callback = temp_callback->next) {
if(temp_callback->priority > new_callback->priority)
break;
last_callback = temp_callback;
}
if(last_callback == NULL)
neb_callback_list[callback_type] = new_callback;
else {
if(temp_callback == NULL)
last_callback->next = new_callback;
else {
new_callback->next = temp_callback;
last_callback->next = new_callback;
}
}
}
return OK;
}
/* dregisters all callback functions for a given module */
int neb_deregister_module_callbacks(nebmodule *mod) {
nebcallback *temp_callback = NULL;
nebcallback *next_callback = NULL;
int callback_type = 0;
if(mod == NULL)
return NEBERROR_NOMODULE;
if(neb_callback_list == NULL)
return OK;
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)
neb_deregister_callback(callback_type, (int(*)(int, void*))temp_callback->callback_func);
}
}
return OK;
}
/* allows a module to deregister a callback function */
int neb_deregister_callback(int callback_type, int (*callback_func)(int, void *)) {
nebcallback *temp_callback = NULL;
nebcallback *last_callback = NULL;
nebcallback *next_callback = NULL;
if(callback_func == NULL)
return NEBERROR_NOCALLBACKFUNC;
if(neb_callback_list == NULL)
return NEBERROR_NOCALLBACKLIST;
/* make sure the callback type is within bounds */
if(callback_type < 0 || callback_type >= NEBCALLBACK_NUMITEMS)
return NEBERROR_CALLBACKBOUNDS;
/* find the callback to remove */
for(temp_callback = last_callback = neb_callback_list[callback_type]; temp_callback != NULL; temp_callback = next_callback) {
next_callback = temp_callback->next;
/* we found it */
if(temp_callback->callback_func == (void *)callback_func)
break;
last_callback = temp_callback;
}
/* we couldn't find the callback */
if(temp_callback == NULL)
return NEBERROR_CALLBACKNOTFOUND;
else {
/* only one item in the list */
if(temp_callback != last_callback->next)
neb_callback_list[callback_type] = NULL;
else
last_callback->next = next_callback;
my_free(temp_callback);
}
return OK;
}
/* make callbacks to modules */
int neb_make_callbacks(int callback_type, void *data) {
nebcallback *temp_callback, *next_callback;
int (*callbackfunc)(int, void *);
register int cbresult = 0;
int total_callbacks = 0;
/* make sure callback list is initialized */
if(neb_callback_list == NULL)
return ERROR;
/* make sure the callback type is within bounds */
if(callback_type < 0 || callback_type >= NEBCALLBACK_NUMITEMS)
return ERROR;
log_debug_info(DEBUGL_EVENTBROKER, 1, "Making callbacks (type %d)...\n", callback_type);
/* make the callbacks... */
for(temp_callback = neb_callback_list[callback_type]; temp_callback; temp_callback = next_callback) {
next_callback = temp_callback->next;
callbackfunc = temp_callback->callback_func;
cbresult = callbackfunc(callback_type, data);
temp_callback = next_callback;
total_callbacks++;
log_debug_info(DEBUGL_EVENTBROKER, 2, "Callback #%d (type %d) return code = %d\n", total_callbacks, callback_type, cbresult);
/* module wants to cancel callbacks to other modules (and potentially cancel the default Nagios handling of an event) */
if(cbresult == NEBERROR_CALLBACKCANCEL)
break;
/* module wants to override default Nagios handling of an event */
/* not sure if we should bail out here just because one module wants to override things - what about other modules? EG 12/11/2006 */
else if(cbresult == NEBERROR_CALLBACKOVERRIDE)
break;
}
return cbresult;
}
/* initialize callback list */
int neb_init_callback_list(void) {
register int x = 0;
/* allocate memory for the callback list */
neb_callback_list = (nebcallback **)malloc(NEBCALLBACK_NUMITEMS * sizeof(nebcallback *));
if(neb_callback_list == NULL)
return ERROR;
/* initialize list pointers */
for(x = 0; x < NEBCALLBACK_NUMITEMS; x++)
neb_callback_list[x] = NULL;
return OK;
}
/* free memory allocated to callback list */
int neb_free_callback_list(void) {
nebcallback *temp_callback = NULL;
nebcallback *next_callback = NULL;
register int x = 0;
if(neb_callback_list == NULL)
return OK;
for(x = 0; x < NEBCALLBACK_NUMITEMS; x++) {
for(temp_callback = neb_callback_list[x]; temp_callback != NULL; temp_callback = next_callback) {
next_callback = temp_callback->next;
my_free(temp_callback);
}
neb_callback_list[x] = NULL;
}
my_free(neb_callback_list);
return OK;
}
#endif
nagios/base/netutils.c 0000664 0000000 0000000 00000014165 12210155146 0015267 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* 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:
*
* 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/netutils.h"
/* connect to a TCP socket in nonblocking fashion */
int my_tcp_connect(char *host_name, int port, int *sd, int timeout) {
struct addrinfo hints;
struct addrinfo *res;
int result;
char port_str[6];
int flags = 0;
fd_set rfds;
fd_set wfds;
struct timeval tv;
int optval;
socklen_t optlen;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
/* make sure our static port_str is long enough */
if(port > 65535)
return ERROR;
snprintf(port_str, sizeof(port_str), "%d", port);
result = getaddrinfo(host_name, port_str, &hints, &res);
if(result != 0) {
/*printf("GETADDRINFO: %s (%s) = %s\n",host_name,port_str,gai_strerror(result));*/
return ERROR;
}
/* create a socket */
*sd = socket(res->ai_family, SOCK_STREAM, res->ai_protocol);
if(*sd < 0) {
freeaddrinfo(res);
return ERROR;
}
/* make socket non-blocking */
flags = fcntl(*sd, F_GETFL, 0);
fcntl(*sd, F_SETFL, flags | O_NONBLOCK);
/* attempt to connect */
result = connect(*sd, res->ai_addr, res->ai_addrlen);
/* immediately successful connect */
if(result == 0) {
result = OK;
/*printf("IMMEDIATE SUCCESS\n");*/
}
/* connection error */
else if(result < 0 && errno != EINPROGRESS) {
result = ERROR;
}
/* connection in progress - wait for it... */
else {
do {
/* set connection timeout */
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&wfds);
FD_SET(*sd, &wfds);
rfds = wfds;
/* wait for readiness */
result = select((*sd) + 1, &rfds, &wfds, NULL, &tv);
/*printf("SELECT RESULT: %d\n",result);*/
/* timeout */
if(result == 0) {
/*printf("TIMEOUT\n");*/
result = ERROR;
break;
}
/* an error occurred */
if(result < 0 && errno != EINTR) {
result = ERROR;
break;
}
/* got something - check it */
else if(result > 0) {
/* get socket options to check for errors */
optlen = sizeof(int);
if(getsockopt(*sd, SOL_SOCKET, SO_ERROR, (void *)(&optval), &optlen) < 0) {
result = ERROR;
break;
}
/* an error occurred in the connection */
if(optval != 0) {
result = ERROR;
break;
}
/* the connection was good! */
/*
printf("CONNECT SELECT: ERRNO=%s\n",strerror(errno));
printf("CONNECT SELECT: OPTVAL=%s\n",strerror(optval));
*/
result = OK;
break;
}
/* some other error occurred */
else {
result = ERROR;
break;
}
}
while(1);
}
freeaddrinfo(res);
return result;
}
/* based on Beej's sendall - thanks Beej! */
int my_sendall(int s, char *buf, int *len, int timeout) {
int total_sent = 0;
int bytes_left = 0;
int n;
fd_set wfds;
struct timeval tv;
int result = OK;
time_t start_time;
time_t current_time;
time(&start_time);
bytes_left = *len;
while(total_sent < *len) {
/* set send timeout */
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&wfds);
FD_SET(s, &wfds);
/* wait for readiness */
result = select(s + 1, NULL, &wfds, NULL, &tv);
/* timeout */
if(result == 0) {
/*printf("RECV SELECT TIMEOUT\n");*/
result = ERROR;
break;
}
/* error */
else if(result < 0) {
/*printf("RECV SELECT ERROR: %s\n",strerror(errno));*/
result = ERROR;
break;
}
/* we're ready to write some data */
result = OK;
/* send the data */
n = send(s, buf + total_sent, bytes_left, 0);
if(n == -1) {
/*printf("SEND ERROR: (%d) %s\n",s,strerror(errno));*/
break;
}
total_sent += n;
bytes_left -= n;
/* make sure we haven't overrun the timeout */
time(¤t_time);
if(current_time - start_time > timeout) {
result = ERROR;
break;
}
}
*len = total_sent;
return result;
}
/* receives all data in non-blocking mode with a timeout - modelled after sendall() */
int my_recvall(int s, char *buf, int *len, int timeout) {
int total_received = 0;
int bytes_left = *len;
int n = 0;
time_t start_time;
time_t current_time;
fd_set rfds;
struct timeval tv;
int result = OK;
/* clear the receive buffer */
bzero(buf, *len);
time(&start_time);
/* receive all data */
while(total_received < *len) {
/* set receive timeout */
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(s, &rfds);
/* wait for readiness */
result = select(s + 1, &rfds, NULL, NULL, &tv);
/* timeout */
if(result == 0) {
/*printf("RECV SELECT TIMEOUT\n");*/
result = ERROR;
break;
}
/* error */
else if(result < 0) {
/*printf("RECV SELECT ERROR: %s\n",strerror(errno));*/
result = ERROR;
break;
}
/* we're ready to read some data */
result = OK;
/* receive some data */
n = recv(s, buf + total_received, bytes_left, 0);
/* server disconnected */
if(n == 0) {
/*printf("SERVER DISCONNECT\n");*/
break;
}
/* apply bytes we received */
total_received += n;
bytes_left -= n;
/* make sure we haven't overrun the timeout */
time(¤t_time);
if(current_time - start_time > timeout) {
result = ERROR;
break;
}
}
/* return number of bytes actually received here */
*len = total_received;
return result;
}
nagios/base/notifications.c 0000664 0000000 0000000 00000250560 12210155146 0016272 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* 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:
*
* 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/macros.h"
#include "../include/nagios.h"
#include "../include/broker.h"
#include "../include/neberrors.h"
extern notification *notification_list;
extern contact *contact_list;
extern serviceescalation *serviceescalation_list;
extern hostescalation *hostescalation_list;
extern time_t program_start;
extern int interval_length;
extern int log_notifications;
extern int enable_notifications;
extern int notification_timeout;
extern unsigned long next_notification_id;
extern char *generic_summary;
/******************************************************************/
/***************** SERVICE NOTIFICATION FUNCTIONS *****************/
/******************************************************************/
/* notify contacts about a service problem or recovery */
int service_notification(service *svc, int type, char *not_author, char *not_data, int options) {
host *temp_host = NULL;
notification *temp_notification = NULL;
contact *temp_contact = NULL;
time_t current_time;
struct timeval start_time;
struct timeval end_time;
int escalated = FALSE;
int result = OK;
int contacts_notified = 0;
int increment_notification_number = FALSE;
nagios_macros mac;
int neb_result;
log_debug_info(DEBUGL_FUNCTIONS, 0, "service_notification()\n");
/* get the current time */
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));
/* if we couldn't find the host, return an error */
if((temp_host = svc->host_ptr) == NULL) {
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Couldn't find the host associated with this service, so we won't send a notification!\n");
return ERROR;
}
/* 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");
return OK;
}
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Notification viability test passed.\n");
/* should the notification number be increased? */
if(type == NOTIFICATION_NORMAL || (options & NOTIFICATION_OPTION_INCREMENT)) {
svc->current_notification_number++;
increment_notification_number = TRUE;
}
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Current notification number: %d (%s)\n", svc->current_notification_number, (increment_notification_number == TRUE) ? "incremented" : "unchanged");
/* save and increase the current notification id */
svc->current_notification_id = next_notification_id;
next_notification_id++;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Creating list of contacts to be notified.\n");
#ifdef USE_EVENT_BROKER
/* send data to event broker */
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) {
free_notification_list();
return ERROR;
}
else if(NEBERROR_CALLBACKOVERRIDE == neb_result) {
free_notification_list();
return OK;
}
#endif
/* allocate memory for macros */
memset(&mac, 0, sizeof(mac));
/* 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
*/
create_notification_list_from_service(&mac, svc, options, &escalated, type);
/* XXX: crazy indent */
/* we have contacts to notify... */
if(notification_list != NULL) {
/* grab the macro variables */
grab_host_macros_r(&mac, temp_host);
grab_service_macros_r(&mac, svc);
/* 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;
}
}
}
/* get author and comment macros */
if(not_author)
mac.x[MACRO_NOTIFICATIONAUTHOR] = strdup(not_author);
if(temp_contact != NULL) {
mac.x[MACRO_NOTIFICATIONAUTHORNAME] = strdup(temp_contact->name);
mac.x[MACRO_NOTIFICATIONAUTHORALIAS] = strdup(temp_contact->alias);
}
if(not_data)
mac.x[MACRO_NOTIFICATIONCOMMENT] = strdup(not_data);
/* NOTE: these macros are deprecated and will likely disappear in Nagios 4.x */
/* if this is an acknowledgement, get author and comment macros */
if(type == NOTIFICATION_ACKNOWLEDGEMENT) {
if(not_author)
mac.x[MACRO_SERVICEACKAUTHOR] = strdup(not_author);
if(not_data)
mac.x[MACRO_SERVICEACKCOMMENT] = strdup(not_data);
if(temp_contact != NULL) {
mac.x[MACRO_SERVICEACKAUTHORNAME] = strdup(temp_contact->name);
mac.x[MACRO_SERVICEACKAUTHORALIAS] = strdup(temp_contact->alias);
}
}
/* set the notification type macro */
if(type == NOTIFICATION_ACKNOWLEDGEMENT)
mac.x[MACRO_NOTIFICATIONTYPE] = "ACKNOWLEDGEMENT";
else if(type == NOTIFICATION_FLAPPINGSTART)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGSTART";
else if(type == NOTIFICATION_FLAPPINGSTOP)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGSTOP";
else if(type == NOTIFICATION_FLAPPINGDISABLED)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGDISABLED";
else if(type == NOTIFICATION_DOWNTIMESTART)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMESTART";
else if(type == NOTIFICATION_DOWNTIMEEND)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMEEND";
else if(type == NOTIFICATION_DOWNTIMECANCELLED)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMECANCELLED";
else if(type == NOTIFICATION_CUSTOM)
mac.x[MACRO_NOTIFICATIONTYPE] = "CUSTOM";
else if(svc->current_state == STATE_OK)
mac.x[MACRO_NOTIFICATIONTYPE] = "RECOVERY";
else
mac.x[MACRO_NOTIFICATIONTYPE] = "PROBLEM";
mac.x[MACRO_NOTIFICATIONTYPE] = strdup(mac.x[MACRO_NOTIFICATIONTYPE]);
/* set the notification number macro */
asprintf(&mac.x[MACRO_SERVICENOTIFICATIONNUMBER], "%d", svc->current_notification_number);
/* the $NOTIFICATIONNUMBER$ macro is maintained for backward compatability */
mac.x[MACRO_NOTIFICATIONNUMBER] = strdup(mac.x[MACRO_SERVICENOTIFICATIONNUMBER]);
/* set the notification id macro */
asprintf(&mac.x[MACRO_SERVICENOTIFICATIONID], "%lu", svc->current_notification_id);
/* notify each contact (duplicates have been removed) */
for(temp_notification = notification_list; temp_notification != NULL; temp_notification = temp_notification->next) {
/* grab the macro variables for this contact */
grab_contact_macros_r(&mac, temp_notification->contact);
/* notify this contact */
result = notify_contact_of_service(&mac, temp_notification->contact, svc, type, not_author, not_data, options, escalated);
/* keep track of how many contacts were notified */
if(result == OK)
contacts_notified++;
}
/* free memory allocated to the notification list */
free_notification_list();
/* clear out all macros we created */
my_free(mac.x[MACRO_NOTIFICATIONNUMBER]);
my_free(mac.x[MACRO_SERVICENOTIFICATIONNUMBER]);
my_free(mac.x[MACRO_SERVICENOTIFICATIONID]);
my_free(mac.x[MACRO_NOTIFICATIONCOMMENT]);
my_free(mac.x[MACRO_NOTIFICATIONTYPE]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHOR]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHORNAME]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHORALIAS]);
my_free(mac.x[MACRO_SERVICEACKAUTHORNAME]);
my_free(mac.x[MACRO_SERVICEACKAUTHORALIAS]);
my_free(mac.x[MACRO_SERVICEACKAUTHOR]);
my_free(mac.x[MACRO_SERVICEACKCOMMENT]);
/* this gets set in add_notification() */
my_free(mac.x[MACRO_NOTIFICATIONRECIPIENTS]);
/*
* Clear all macros, or they will linger in memory
* now that we're done with the notifications.
*/
clear_summary_macros_r(&mac);
clear_contact_macros_r(&mac);
clear_argv_macros_r(&mac);
clear_host_macros_r(&mac);
clear_service_macros_r(&mac);
if(type == NOTIFICATION_NORMAL) {
/* adjust last/next notification time and notification flags if we notified someone */
if(contacts_notified > 0) {
/* calculate the next acceptable re-notification time */
svc->next_notification = get_next_service_notification_time(svc, current_time);
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "%d contacts were notified. Next possible notification time: %s", contacts_notified, ctime(&svc->next_notification));
/* update the last notification time for this service (this is needed for rescheduling later notifications) */
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;
}
/* we didn't end up notifying anyone */
else if(increment_notification_number == TRUE) {
/* adjust current notification number */
svc->current_notification_number--;
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "No contacts were notified. Next possible notification time: %s", ctime(&svc->next_notification));
}
}
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "%d contacts were notified.\n", contacts_notified);
}
/* there were no contacts, so no notification really occurred... */
else {
/* readjust current notification number, since one didn't go out */
if(increment_notification_number == TRUE)
svc->current_notification_number--;
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "No contacts were found for notification purposes. No notification was sent out.\n");
}
/* this gets set in create_notification_list_from_service() */
my_free(mac.x[MACRO_NOTIFICATIONISESCALATED]);
/* get the time we finished */
gettimeofday(&end_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_notification_data(NEBTYPE_NOTIFICATION_END, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, start_time, end_time, (void *)svc, not_author, not_data, escalated, contacts_notified, NULL);
#endif
/* update the status log with the service information */
update_service_status(svc, FALSE);
return OK;
}
/* checks the viability of sending out a service alert (top level filters) */
int check_service_notification_viability(service *svc, int type, int options) {
host *temp_host;
timeperiod *temp_period;
time_t current_time;
time_t timeperiod_start;
time_t first_problem_time;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_service_notification_viability()\n");
/* forced notifications bust through everything */
if(options & NOTIFICATION_OPTION_FORCED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This is a forced service notification, so we'll send it out.\n");
return OK;
}
/* get current time */
time(¤t_time);
/* are notifications enabled? */
if(enable_notifications == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Notifications are disabled, so service notifications will not be sent out.\n");
return ERROR;
}
/* find the host this service is associated with */
if((temp_host = (host *)svc->host_ptr) == NULL)
return ERROR;
/* if we couldn't find the host, return an error */
if(temp_host == NULL) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Couldn't find the host associated with this service, so we won't send a notification.\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) {
temp_period = svc->host_ptr->notification_period_ptr;
}
/* see if the service can have notifications sent out at this time */
if(check_time_against_period(current_time, temp_period) == ERROR) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service shouldn't have notifications sent out at this time.\n");
/* calculate the next acceptable notification time, once the next valid time range arrives... */
if(type == NOTIFICATION_NORMAL) {
get_next_valid_time(current_time, &timeperiod_start, svc->notification_period_ptr);
/* looks like there are no valid notification times defined, so schedule the next one far into the future (one year)... */
if(timeperiod_start == (time_t)0)
svc->next_notification = (time_t)(current_time + (60 * 60 * 24 * 365));
/* else use the next valid notification time */
else
svc->next_notification = timeperiod_start;
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Next possible notification time: %s\n", ctime(&svc->next_notification));
}
return ERROR;
}
/* are notifications temporarily disabled for this service? */
if(svc->notifications_enabled == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Notifications are temporarily disabled for this service, so we won't send one out.\n");
return ERROR;
}
/*********************************************/
/*** SPECIAL CASE FOR CUSTOM NOTIFICATIONS ***/
/*********************************************/
/* custom notifications are good to go at this point... */
if(type == NOTIFICATION_CUSTOM) {
if(svc->scheduled_downtime_depth > 0 || temp_host->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't send custom notification during scheduled downtime.\n");
return ERROR;
}
return OK;
}
/****************************************/
/*** SPECIAL CASE FOR ACKNOWLEGEMENTS ***/
/****************************************/
/* acknowledgements only have to pass three general filters, although they have another test of their own... */
if(type == NOTIFICATION_ACKNOWLEDGEMENT) {
/* don't send an acknowledgement if there isn't a problem... */
if(svc->current_state == STATE_OK) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "The service is currently OK, so we won't send an acknowledgement.\n");
return ERROR;
}
/* acknowledgement viability test passed, so the notification can be sent out */
return OK;
}
/****************************************/
/*** SPECIAL CASE FOR FLAPPING ALERTS ***/
/****************************************/
/* flapping notifications only have to pass three general filters */
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) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about FLAPPING events for this service.\n");
return ERROR;
}
/* don't send notifications during scheduled downtime */
if(svc->scheduled_downtime_depth > 0 || temp_host->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about FLAPPING events during scheduled downtime.\n");
return ERROR;
}
/* flapping viability test passed, so the notification can be sent out */
return OK;
}
/****************************************/
/*** SPECIAL CASE FOR DOWNTIME ALERTS ***/
/****************************************/
/* downtime notifications only have to pass three general filters */
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) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about DOWNTIME events for this service.\n");
return ERROR;
}
/* don't send notifications during scheduled downtime (for service only, not host) */
if(svc->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about DOWNTIME events during scheduled downtime.\n");
return ERROR;
}
/* downtime viability test passed, so the notification can be sent out */
return OK;
}
/****************************************/
/*** NORMAL NOTIFICATIONS ***************/
/****************************************/
/* is this a hard problem/recovery? */
if(svc->state_type == SOFT_STATE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service is in a soft state, so we won't send a notification out.\n");
return ERROR;
}
/* has this problem already been acknowledged? */
if(svc->problem_has_been_acknowledged == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service problem has already been acknowledged, so we won't send a notification out.\n");
return ERROR;
}
/* check service notification dependencies */
if(check_service_dependencies(svc, NOTIFICATION_DEPENDENCY) == DEPENDENCIES_FAILED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Service notification dependencies for this service have failed, so we won't sent a notification out.\n");
return ERROR;
}
/* check host notification dependencies */
if(check_host_dependencies(temp_host, NOTIFICATION_DEPENDENCY) == DEPENDENCIES_FAILED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Host notification dependencies for this service have failed, so we won't sent a notification out.\n");
return ERROR;
}
/* 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");
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");
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 */
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;
if(current_time < (time_t)((first_problem_time == (time_t)0L) ? program_start : 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;
}
}
/* if this service is currently flapping, don't send the notification */
if(svc->is_flapping == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service is currently flapping, so we won't send notifications.\n");
return ERROR;
}
/***** RECOVERY NOTIFICATIONS ARE GOOD TO GO AT THIS POINT *****/
if(svc->current_state == STATE_OK)
return OK;
/* don't notify contacts about this service problem again if the notification interval is set to 0 */
if(svc->no_more_notifications == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't re-notify contacts about this service problem.\n");
return ERROR;
}
/* if the host is down or unreachable, don't notify contacts about service failures */
if(temp_host->current_state != HOST_UP) {
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;
}
/* don't notify if we haven't waited long enough since the last time (and the service is not marked as being volatile) */
if((current_time < svc->next_notification) && svc->is_volatile == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We haven't waited long enough to re-notify contacts about this service.\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Next valid notification time: %s", ctime(&svc->next_notification));
return ERROR;
}
/* if this service is currently in a scheduled downtime period, don't send the notification */
if(svc->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service is currently in a scheduled downtime, so we won't send notifications.\n");
return ERROR;
}
/* if this host is currently in a scheduled downtime period, don't send the notification */
if(temp_host->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "The host this service is associated with is currently in a scheduled downtime, so we won't send notifications.\n");
return ERROR;
}
return OK;
}
/* check viability of sending out a service notification to a specific contact (contact-specific filters) */
int check_contact_service_notification_viability(contact *cntct, service *svc, int type, int options) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_contact_service_notification_viability()\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Checking service notification viability for contact '%s'...\n", cntct->name);
/* forced notifications bust through everything */
if(options & NOTIFICATION_OPTION_FORCED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This is a forced service notification, so we'll send it out to this contact.\n");
return OK;
}
/* are notifications enabled? */
if(cntct->service_notifications_enabled == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Service notifications are disabled for this contact.\n");
return ERROR;
}
/* see if the contact can be notified at this time */
if(check_time_against_period(time(NULL), cntct->service_notification_period_ptr) == ERROR) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "This contact shouldn't be notified at this time.\n");
return ERROR;
}
/*********************************************/
/*** SPECIAL CASE FOR CUSTOM NOTIFICATIONS ***/
/*********************************************/
/* custom notifications are good to go at this point... */
if(type == NOTIFICATION_CUSTOM)
return OK;
/****************************************/
/*** SPECIAL CASE FOR FLAPPING ALERTS ***/
/****************************************/
if(type == NOTIFICATION_FLAPPINGSTART || type == NOTIFICATION_FLAPPINGSTOP || type == NOTIFICATION_FLAPPINGDISABLED) {
if(cntct->notify_on_service_flapping == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about FLAPPING service events.\n");
return ERROR;
}
return OK;
}
/****************************************/
/*** SPECIAL CASE FOR DOWNTIME ALERTS ***/
/****************************************/
if(type == NOTIFICATION_DOWNTIMESTART || type == NOTIFICATION_DOWNTIMEEND || type == NOTIFICATION_DOWNTIMECANCELLED) {
if(cntct->notify_on_service_downtime == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about DOWNTIME service events.\n");
return ERROR;
}
return OK;
}
/*************************************/
/*** ACKS AND NORMAL NOTIFICATIONS ***/
/*************************************/
/* 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");
return ERROR;
}
if(svc->current_state == STATE_OK) {
if(cntct->notify_on_service_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))) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify about this recovery.\n");
return ERROR;
}
}
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Service notification viability for contact '%s' PASSED.\n", cntct->name);
return OK;
}
/* notify a specific contact about a service problem or recovery */
int notify_contact_of_service(nagios_macros *mac, contact *cntct, service *svc, int type, char *not_author, char *not_data, int options, int escalated) {
commandsmember *temp_commandsmember = NULL;
char *command_name = NULL;
char *command_name_ptr = NULL;
char *raw_command = NULL;
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);
/* get start time */
gettimeofday(&start_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_contact_notification_data(NEBTYPE_CONTACTNOTIFICATION_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, start_time, end_time, (void *)svc, cntct, not_author, not_data, escalated, NULL);
if(NEBERROR_CALLBACKCANCEL == neb_result)
return ERROR;
else if(NEBERROR_CALLBACKOVERRIDE == neb_result)
return OK;
#endif
/* process all the notification commands this user has */
for(temp_commandsmember = cntct->service_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) {
/* get start time */
gettimeofday(&method_start_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
method_end_time.tv_sec = 0L;
method_end_time.tv_usec = 0L;
neb_result = broker_contact_notification_method_data(NEBTYPE_CONTACTNOTIFICATIONMETHOD_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, method_start_time, method_end_time, (void *)svc, cntct, temp_commandsmember->command, not_author, not_data, escalated, NULL);
if(NEBERROR_CALLBACKCANCEL == neb_result)
break ;
else if(NEBERROR_CALLBACKOVERRIDE == neb_result)
continue ;
#endif
/* get the raw command line */
get_raw_command_line_r(mac, temp_commandsmember->command_ptr, temp_commandsmember->command, &raw_command, macro_options);
if(raw_command == NULL)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Raw notification command: %s\n", raw_command);
/* process any macros contained in the argument */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
continue;
/* get the command name */
command_name = (char *)strdup(temp_commandsmember->command);
command_name_ptr = strtok(command_name, "!");
/* run the notification command... */
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Processed notification command: %s\n", processed_command);
/* log the notification to program log file */
if(log_notifications == TRUE) {
switch(type) {
case NOTIFICATION_CUSTOM:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;CUSTOM ($SERVICESTATE$);%s;$SERVICEOUTPUT$;$NOTIFICATIONAUTHOR$;$NOTIFICATIONCOMMENT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_ACKNOWLEDGEMENT:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;ACKNOWLEDGEMENT ($SERVICESTATE$);%s;$SERVICEOUTPUT$;$NOTIFICATIONAUTHOR$;$NOTIFICATIONCOMMENT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGSTART:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;FLAPPINGSTART ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGSTOP:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;FLAPPINGSTOP ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGDISABLED:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;FLAPPINGDISABLED ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMESTART:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;DOWNTIMESTART ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMEEND:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;DOWNTIMEEND ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMECANCELLED:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;DOWNTIMECANCELLED ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
default:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;$SERVICESTATE$;%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
}
process_macros_r(mac, temp_buffer, &processed_buffer, 0);
write_to_all_logs(processed_buffer, NSLOG_SERVICE_NOTIFICATION);
my_free(temp_buffer);
my_free(processed_buffer);
}
/* 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);
}
/* free memory */
my_free(command_name);
my_free(processed_command);
/* get end time */
gettimeofday(&method_end_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_contact_notification_method_data(NEBTYPE_CONTACTNOTIFICATIONMETHOD_END, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, method_start_time, method_end_time, (void *)svc, cntct, temp_commandsmember->command, not_author, not_data, escalated, NULL);
#endif
}
/* get end time */
gettimeofday(&end_time, NULL);
/* update the contact's last service notification time */
cntct->last_service_notification = start_time.tv_sec;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_contact_notification_data(NEBTYPE_CONTACTNOTIFICATION_END, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, start_time, end_time, (void *)svc, cntct, not_author, not_data, escalated, NULL);
#endif
return OK;
}
/* checks to see if a service escalation entry is a match for the current service notification */
int is_valid_escalation_for_service_notification(service *svc, serviceescalation *se, int options) {
int notification_number = 0;
time_t current_time = 0L;
service *temp_service = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "is_valid_escalation_for_service_notification()\n");
/* get the current time */
time(¤t_time);
/* if this is a recovery, really we check for who got notified about a previous problem */
if(svc->current_state == STATE_OK)
notification_number = svc->current_notification_number - 1;
else
notification_number = svc->current_notification_number;
/* this entry if it is not for this service */
temp_service = se->service_ptr;
if(temp_service == NULL || temp_service != svc)
return FALSE;
/*** EXCEPTION ***/
/* broadcast options go to everyone, so this escalation is valid */
if(options & NOTIFICATION_OPTION_BROADCAST)
return TRUE;
/* skip this escalation if it happens later */
if(se->first_notification > notification_number)
return FALSE;
/* skip this escalation if it has already passed */
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)
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)
return FALSE;
return TRUE;
}
/* 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;
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)) {
/* we found a matching entry, so escalate this notification! */
if(is_valid_escalation_for_service_notification(svc, temp_se, NOTIFICATION_OPTION_NONE) == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Service notification WILL be escalated.\n");
return TRUE;
}
}
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Service notification will NOT be escalated.\n");
return FALSE;
}
/* given a service, create a list of contacts to be notified, removing duplicates, checking contact notification viability */
int create_notification_list_from_service(nagios_macros *mac, service *svc, int options, int *escalated, int type) {
serviceescalation *temp_se = NULL;
contactsmember *temp_contactsmember = NULL;
contact *temp_contact = NULL;
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");
/* see if this notification should be escalated */
escalate_notification = should_service_notification_be_escalated(svc);
/* set the escalation flag */
*escalated = escalate_notification;
/* make sure there aren't any leftover contacts */
free_notification_list();
/* set the escalation macro */
mac->x[MACRO_NOTIFICATIONISESCALATED] = strdup(escalate_notification ? "1" : "0");
if(options & NOTIFICATION_OPTION_BROADCAST)
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This notification will be BROADCAST to all (escalated and normal) contacts...\n");
/* use escalated contacts for this notification */
if(escalate_notification == TRUE || (options & NOTIFICATION_OPTION_BROADCAST)) {
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)) {
/* skip this entry if it isn't appropriate */
if(is_valid_escalation_for_service_notification(svc, temp_se, options) == FALSE)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding individual contacts from service escalation(s) to notification list.\n");
/* add all individual contacts for this escalation entry */
for(temp_contactsmember = temp_se->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_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, "Adding members of contact groups from service escalation(s) to notification list.\n");
/* add all contacts that belong to contactgroups for this escalation */
for(temp_contactgroupsmember = temp_se->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact group '%s' for service escalation to notification list.\n", temp_contactgroupsmember->group_name);
if((temp_contactgroup = temp_contactgroupsmember->group_ptr) == NULL)
continue;
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);
}
}
}
}
/* else use normal, non-escalated contacts */
if(escalate_notification == FALSE || (options & NOTIFICATION_OPTION_BROADCAST)) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Adding normal contacts for service to notification list.\n");
/* add all individual contacts for this service */
for(temp_contactsmember = svc->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_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 */
for(temp_contactgroupsmember = svc->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact group '%s' for service to notification list.\n", temp_contactgroupsmember->group_name);
if((temp_contactgroup = temp_contactgroupsmember->group_ptr) == NULL)
continue;
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);
}
}
}
return OK;
}
/******************************************************************/
/******************* HOST NOTIFICATION FUNCTIONS ******************/
/******************************************************************/
/* notify all contacts for a host that the entire host is down or up */
int host_notification(host *hst, int type, char *not_author, char *not_data, int options) {
notification *temp_notification = NULL;
contact *temp_contact = NULL;
time_t current_time;
struct timeval start_time;
struct timeval end_time;
int escalated = FALSE;
int result = OK;
int contacts_notified = 0;
int increment_notification_number = FALSE;
nagios_macros mac;
int neb_result;
/* get the current time */
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));
/* check viability of sending out a host notification */
if(check_host_notification_viability(hst, type, options) == ERROR) {
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Notification viability test failed. No notification will be sent out.\n");
return OK;
}
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Notification viability test passed.\n");
/* should the notification number be increased? */
if(type == NOTIFICATION_NORMAL || (options & NOTIFICATION_OPTION_INCREMENT)) {
hst->current_notification_number++;
increment_notification_number = TRUE;
}
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Current notification number: %d (%s)\n", hst->current_notification_number, (increment_notification_number == TRUE) ? "incremented" : "unchanged");
/* save and increase the current notification id */
hst->current_notification_id = next_notification_id;
next_notification_id++;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Creating list of contacts to be notified.\n");
#ifdef USE_EVENT_BROKER
/* send data to event broker */
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) {
free_notification_list();
return ERROR;
}
else if(NEBERROR_CALLBACKOVERRIDE == neb_result) {
free_notification_list();
return OK;
}
#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
*/
create_notification_list_from_host(&mac, hst, options, &escalated, type);
/* XXX: crazy indent */
/* there are contacts to be notified... */
if(notification_list != NULL) {
/* grab the macro variables */
grab_host_macros_r(&mac, hst);
/* 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;
}
}
}
/* get author and comment macros */
if(not_author)
mac.x[MACRO_NOTIFICATIONAUTHOR] = strdup(not_author);
if(temp_contact != NULL) {
mac.x[MACRO_NOTIFICATIONAUTHORNAME] = strdup(temp_contact->name);
mac.x[MACRO_NOTIFICATIONAUTHORALIAS] = strdup(temp_contact->alias);
}
if(not_data)
mac.x[MACRO_NOTIFICATIONCOMMENT] = strdup(not_data);
/* NOTE: these macros are deprecated and will likely disappear in Nagios 4.x */
/* if this is an acknowledgement, get author and comment macros */
if(type == NOTIFICATION_ACKNOWLEDGEMENT) {
if(not_author)
mac.x[MACRO_HOSTACKAUTHOR] = strdup(not_author);
if(not_data)
mac.x[MACRO_HOSTACKCOMMENT] = strdup(not_data);
if(temp_contact != NULL) {
mac.x[MACRO_HOSTACKAUTHORNAME] = strdup(temp_contact->name);
mac.x[MACRO_HOSTACKAUTHORALIAS] = strdup(temp_contact->alias);
}
}
/* set the notification type macro */
if(type == NOTIFICATION_ACKNOWLEDGEMENT)
mac.x[MACRO_NOTIFICATIONTYPE] = "ACKNOWLEDGEMENT";
else if(type == NOTIFICATION_FLAPPINGSTART)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGSTART";
else if(type == NOTIFICATION_FLAPPINGSTOP)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGSTOP";
else if(type == NOTIFICATION_FLAPPINGDISABLED)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGDISABLED";
else if(type == NOTIFICATION_DOWNTIMESTART)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMESTART";
else if(type == NOTIFICATION_DOWNTIMEEND)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMEEND";
else if(type == NOTIFICATION_DOWNTIMECANCELLED)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMECANCELLED";
else if(type == NOTIFICATION_CUSTOM)
mac.x[MACRO_NOTIFICATIONTYPE] = "CUSTOM";
else if(hst->current_state == HOST_UP)
mac.x[MACRO_NOTIFICATIONTYPE] = "RECOVERY";
else
mac.x[MACRO_NOTIFICATIONTYPE] = "PROBLEM";
mac.x[MACRO_NOTIFICATIONTYPE] = strdup(mac.x[MACRO_NOTIFICATIONTYPE]);
/* set the notification number macro */
asprintf(&mac.x[MACRO_HOSTNOTIFICATIONNUMBER], "%d", hst->current_notification_number);
/* the $NOTIFICATIONNUMBER$ macro is maintained for backward compatability */
mac.x[MACRO_NOTIFICATIONNUMBER] = strdup(mac.x[MACRO_HOSTNOTIFICATIONNUMBER]);
/* set the notification id macro */
asprintf(&mac.x[MACRO_HOSTNOTIFICATIONID], "%lu", hst->current_notification_id);
/* notify each contact (duplicates have been removed) */
for(temp_notification = notification_list; temp_notification != NULL; temp_notification = temp_notification->next) {
/* grab the macro variables for this contact */
grab_contact_macros_r(&mac, temp_notification->contact);
/* clear summary macros (they are customized for each contact) */
clear_summary_macros_r(&mac);
/* notify this contact */
result = notify_contact_of_host(&mac, temp_notification->contact, hst, type, not_author, not_data, options, escalated);
/* keep track of how many contacts were notified */
if(result == OK)
contacts_notified++;
}
/* free memory allocated to the notification list */
free_notification_list();
/* clear out all macros we created */
my_free(mac.x[MACRO_HOSTNOTIFICATIONID]);
my_free(mac.x[MACRO_NOTIFICATIONNUMBER]);
my_free(mac.x[MACRO_NOTIFICATIONCOMMENT]);
my_free(mac.x[MACRO_HOSTNOTIFICATIONNUMBER]);
my_free(mac.x[MACRO_NOTIFICATIONTYPE]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHOR]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHORNAME]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHORALIAS]);
my_free(mac.x[MACRO_HOSTACKAUTHORNAME]);
my_free(mac.x[MACRO_HOSTACKAUTHORALIAS]);
my_free(mac.x[MACRO_HOSTACKAUTHOR]);
my_free(mac.x[MACRO_HOSTACKCOMMENT]);
/* this gets set in add_notification() */
my_free(mac.x[MACRO_NOTIFICATIONRECIPIENTS]);
/*
* Clear all macros, or they will linger in memory
* now that we're done with the notifications.
*/
clear_summary_macros_r(&mac);
clear_contact_macros_r(&mac);
clear_argv_macros_r(&mac);
clear_host_macros_r(&mac);
if(type == NOTIFICATION_NORMAL) {
/* adjust last/next notification time and notification flags if we notified someone */
if(contacts_notified > 0) {
/* calculate the next acceptable re-notification time */
hst->next_host_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;
/* 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;
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "%d contacts were notified. Next possible notification time: %s", contacts_notified, ctime(&hst->next_host_notification));
}
/* we didn't end up notifying anyone */
else if(increment_notification_number == TRUE) {
/* 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, "%d contacts were notified.\n", contacts_notified);
}
/* there were no contacts, so no notification really occurred... */
else {
/* adjust notification number, since no notification actually went out */
if(increment_notification_number == TRUE)
hst->current_notification_number--;
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "No contacts were found for notification purposes. No notification was sent out.\n");
}
/* this gets set in create_notification_list_from_host() */
my_free(mac.x[MACRO_NOTIFICATIONISESCALATED]);
/* get the time we finished */
gettimeofday(&end_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_notification_data(NEBTYPE_NOTIFICATION_END, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, start_time, end_time, (void *)hst, not_author, not_data, escalated, contacts_notified, NULL);
#endif
/* update the status log with the host info */
update_host_status(hst, FALSE);
return OK;
}
/* checks viability of sending a host notification */
int check_host_notification_viability(host *hst, int type, int options) {
time_t current_time;
time_t timeperiod_start;
time_t first_problem_time;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_host_notification_viability()\n");
/* forced notifications bust through everything */
if(options & NOTIFICATION_OPTION_FORCED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This is a forced host notification, so we'll send it out.\n");
return OK;
}
/* get current time */
time(¤t_time);
/* are notifications enabled? */
if(enable_notifications == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Notifications are disabled, so host notifications will not be sent out.\n");
return ERROR;
}
/* see if the host can have notifications sent out at this time */
if(check_time_against_period(current_time, hst->notification_period_ptr) == ERROR) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This host shouldn't have notifications sent out at this time.\n");
/* if this is a normal notification, calculate the next acceptable notification time, once the next valid time range arrives... */
if(type == NOTIFICATION_NORMAL) {
get_next_valid_time(current_time, &timeperiod_start, hst->notification_period_ptr);
/* 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));
/* else use the next valid notification time */
else
hst->next_host_notification = timeperiod_start;
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Next possible notification time: %s\n", ctime(&hst->next_host_notification));
}
return ERROR;
}
/* are notifications temporarily disabled for this host? */
if(hst->notifications_enabled == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Notifications are temporarily disabled for this host, so we won't send one out.\n");
return ERROR;
}
/*********************************************/
/*** SPECIAL CASE FOR CUSTOM NOTIFICATIONS ***/
/*********************************************/
/* custom notifications are good to go at this point... */
if(type == NOTIFICATION_CUSTOM) {
if(hst->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't send custom notification during scheduled downtime.\n");
return ERROR;
}
return OK;
}
/****************************************/
/*** SPECIAL CASE FOR ACKNOWLEGEMENTS ***/
/****************************************/
/* acknowledgements only have to pass three general filters, although they have another test of their own... */
if(type == NOTIFICATION_ACKNOWLEDGEMENT) {
/* don't send an acknowledgement if there isn't a problem... */
if(hst->current_state == HOST_UP) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "The host is currently UP, so we won't send an acknowledgement.\n");
return ERROR;
}
/* acknowledgement viability test passed, so the notification can be sent out */
return OK;
}
/*****************************************/
/*** SPECIAL CASE FOR FLAPPING ALERTS ***/
/*****************************************/
/* flapping notifications only have to pass three general filters */
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) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about FLAPPING events for this host.\n");
return ERROR;
}
/* don't send notifications during scheduled downtime */
if(hst->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about FLAPPING events during scheduled downtime.\n");
return ERROR;
}
/* flapping viability test passed, so the notification can be sent out */
return OK;
}
/*****************************************/
/*** SPECIAL CASE FOR DOWNTIME ALERTS ***/
/*****************************************/
/* flapping notifications only have to pass three general filters */
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) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about DOWNTIME events for this host.\n");
return ERROR;
}
/* don't send notifications during scheduled downtime */
if(hst->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about DOWNTIME events during scheduled downtime!\n");
return ERROR;
}
/* downtime viability test passed, so the notification can be sent out */
return OK;
}
/****************************************/
/*** NORMAL NOTIFICATIONS ***************/
/****************************************/
/* is this a hard problem/recovery? */
if(hst->state_type == SOFT_STATE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This host is in a soft state, so we won't send a notification out.\n");
return ERROR;
}
/* has this problem already been acknowledged? */
if(hst->problem_has_been_acknowledged == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This host problem has already been acknowledged, so we won't send a notification out!\n");
return ERROR;
}
/* check notification dependencies */
if(check_host_dependencies(hst, NOTIFICATION_DEPENDENCY) == DEPENDENCIES_FAILED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Notification dependencies for this host have failed, so we won't sent a notification out!\n");
return ERROR;
}
/* 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");
return ERROR;
}
if(hst->current_state == HOST_UP) {
if(hst->notify_on_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)) {
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 up (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 */
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;
if(current_time < (time_t)((first_problem_time == (time_t)0L) ? program_start : 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;
}
}
/* if this host is currently flapping, don't send the notification */
if(hst->is_flapping == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This host is currently flapping, so we won't send notifications.\n");
return ERROR;
}
/***** RECOVERY NOTIFICATIONS ARE GOOD TO GO AT THIS POINT *****/
if(hst->current_state == HOST_UP)
return OK;
/* if this host is currently in a scheduled downtime period, don't send the notification */
if(hst->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This host is currently in a scheduled downtime, so we won't send notifications.\n");
return ERROR;
}
/* check if we shouldn't renotify contacts about the host problem */
if(hst->no_more_notifications == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't re-notify contacts about this host problem.\n");
return ERROR;
}
/* check if its time to re-notify the contacts about the host... */
if(current_time < hst->next_host_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));
return ERROR;
}
return OK;
}
/* checks the viability of notifying a specific contact about a host */
int check_contact_host_notification_viability(contact *cntct, host *hst, int type, int options) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_contact_host_notification_viability()\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Checking host notification viability for contact '%s'...\n", cntct->name);
/* forced notifications bust through everything */
if(options & NOTIFICATION_OPTION_FORCED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "This is a forced host notification, so we'll send it out for this contact.\n");
return OK;
}
/* are notifications enabled? */
if(cntct->host_notifications_enabled == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Host notifications are disabled for this contact.\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");
return ERROR;
}
/*********************************************/
/*** SPECIAL CASE FOR CUSTOM NOTIFICATIONS ***/
/*********************************************/
/* custom notifications are good to go at this point... */
if(type == NOTIFICATION_CUSTOM)
return OK;
/****************************************/
/*** SPECIAL CASE FOR FLAPPING ALERTS ***/
/****************************************/
if(type == NOTIFICATION_FLAPPINGSTART || type == NOTIFICATION_FLAPPINGSTOP || type == NOTIFICATION_FLAPPINGDISABLED) {
if(cntct->notify_on_host_flapping == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about FLAPPING host events.\n");
return ERROR;
}
return OK;
}
/****************************************/
/*** SPECIAL CASE FOR DOWNTIME ALERTS ***/
/****************************************/
if(type == NOTIFICATION_DOWNTIMESTART || type == NOTIFICATION_DOWNTIMEEND || type == NOTIFICATION_DOWNTIMECANCELLED) {
if(cntct->notify_on_host_downtime == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about DOWNTIME host events.\n");
return ERROR;
}
return OK;
}
/*************************************/
/*** ACKS AND NORMAL NOTIFICATIONS ***/
/*************************************/
/* 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");
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");
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;
}
/* notify a specific contact that an entire host is down or up */
int notify_contact_of_host(nagios_macros *mac, contact *cntct, host *hst, int type, char *not_author, char *not_data, int options, int escalated) {
commandsmember *temp_commandsmember = NULL;
char *command_name = NULL;
char *command_name_ptr = NULL;
char *temp_buffer = NULL;
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;
struct timeval 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_host()\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Notifying contact '%s'\n", cntct->name);
/* get start time */
gettimeofday(&start_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_contact_notification_data(NEBTYPE_CONTACTNOTIFICATION_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, start_time, end_time, (void *)hst, cntct, not_author, not_data, escalated, NULL);
if(NEBERROR_CALLBACKCANCEL == neb_result)
return ERROR;
else if(NEBERROR_CALLBACKOVERRIDE == neb_result)
return OK;
#endif
/* process all the notification commands this user has */
for(temp_commandsmember = cntct->host_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) {
/* get start time */
gettimeofday(&method_start_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
method_end_time.tv_sec = 0L;
method_end_time.tv_usec = 0L;
neb_result = broker_contact_notification_method_data(NEBTYPE_CONTACTNOTIFICATIONMETHOD_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, method_start_time, method_end_time, (void *)hst, cntct, temp_commandsmember->command, not_author, not_data, escalated, NULL);
if(NEBERROR_CALLBACKCANCEL == neb_result)
break ;
else if(NEBERROR_CALLBACKOVERRIDE == neb_result)
continue ;
#endif
/* get the raw command line */
get_raw_command_line_r(mac, temp_commandsmember->command_ptr, temp_commandsmember->command, &raw_command, macro_options);
if(raw_command == NULL)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Raw notification command: %s\n", raw_command);
/* process any macros contained in the argument */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
continue;
/* get the command name */
command_name = (char *)strdup(temp_commandsmember->command);
command_name_ptr = strtok(command_name, "!");
/* run the notification command... */
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Processed notification command: %s\n", processed_command);
/* log the notification to program log file */
if(log_notifications == TRUE) {
switch(type) {
case NOTIFICATION_CUSTOM:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;CUSTOM ($HOSTSTATE$);%s;$HOSTOUTPUT$;$NOTIFICATIONAUTHOR$;$NOTIFICATIONCOMMENT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_ACKNOWLEDGEMENT:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;ACKNOWLEDGEMENT ($HOSTSTATE$);%s;$HOSTOUTPUT$;$NOTIFICATIONAUTHOR$;$NOTIFICATIONCOMMENT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGSTART:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;FLAPPINGSTART ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGSTOP:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;FLAPPINGSTOP ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGDISABLED:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;FLAPPINGDISABLED ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMESTART:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;DOWNTIMESTART ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMEEND:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;DOWNTIMEEND ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMECANCELLED:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;DOWNTIMECANCELLED ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
default:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;$HOSTSTATE$;%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
}
process_macros_r(mac, temp_buffer, &processed_buffer, 0);
write_to_all_logs(processed_buffer, NSLOG_HOST_NOTIFICATION);
my_free(temp_buffer);
my_free(processed_buffer);
}
/* run the notification command */
my_system_r(mac, processed_command, notification_timeout, &early_timeout, &exectime, NULL, 0);
/* 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);
}
/* free memory */
my_free(command_name);
my_free(processed_command);
/* get end time */
gettimeofday(&method_end_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_contact_notification_method_data(NEBTYPE_CONTACTNOTIFICATIONMETHOD_END, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, method_start_time, method_end_time, (void *)hst, cntct, temp_commandsmember->command, not_author, not_data, escalated, NULL);
#endif
}
/* get end time */
gettimeofday(&end_time, NULL);
/* update the contact's last host notification time */
cntct->last_host_notification = start_time.tv_sec;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_contact_notification_data(NEBTYPE_CONTACTNOTIFICATION_END, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, start_time, end_time, (void *)hst, cntct, not_author, not_data, escalated, NULL);
#endif
return OK;
}
/* checks to see if a host escalation entry is a match for the current host notification */
int is_valid_escalation_for_host_notification(host *hst, hostescalation *he, int options) {
int notification_number = 0;
time_t current_time = 0L;
host *temp_host = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "is_valid_escalation_for_host_notification()\n");
/* get the current time */
time(¤t_time);
/* if this is a recovery, really we check for who got notified about a previous problem */
if(hst->current_state == HOST_UP)
notification_number = hst->current_notification_number - 1;
else
notification_number = hst->current_notification_number;
/* find the host this escalation entry is associated with */
temp_host = he->host_ptr;
if(temp_host == NULL || temp_host != hst)
return FALSE;
/*** EXCEPTION ***/
/* broadcast options go to everyone, so this escalation is valid */
if(options & NOTIFICATION_OPTION_BROADCAST)
return TRUE;
/* skip this escalation if it happens later */
if(he->first_notification > notification_number)
return FALSE;
/* skip this escalation if it has already passed */
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)
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)
return FALSE;
return TRUE;
}
/* 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;
log_debug_info(DEBUGL_FUNCTIONS, 0, "should_host_notification_be_escalated()\n");
if(hst == NULL)
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)) {
/* 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;
}
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Host notification will NOT be escalated.\n");
return FALSE;
}
/* given a host, create a list of contacts to be notified, removing duplicates, checking contact notification viability */
int create_notification_list_from_host(nagios_macros *mac, host *hst, int options, int *escalated, int type) {
hostescalation *temp_he = NULL;
contactsmember *temp_contactsmember = NULL;
contact *temp_contact = NULL;
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");
/* see if this notification should be escalated */
escalate_notification = should_host_notification_be_escalated(hst);
/* set the escalation flag */
*escalated = escalate_notification;
/* make sure there aren't any leftover contacts */
free_notification_list();
/* set the escalation macro */
mac->x[MACRO_NOTIFICATIONISESCALATED] = strdup(escalate_notification ? "1" : "0");
if(options & NOTIFICATION_OPTION_BROADCAST)
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This notification will be BROADCAST to all (escalated and normal) contacts...\n");
/* use escalated contacts for this notification */
if(escalate_notification == TRUE || (options & NOTIFICATION_OPTION_BROADCAST)) {
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)) {
/* see if this escalation if valid for this notification */
if(is_valid_escalation_for_host_notification(hst, temp_he, options) == FALSE)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding individual contacts from host escalation(s) to notification list.\n");
/* add all individual contacts for this escalation */
for(temp_contactsmember = temp_he->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);
}
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact groups from host escalation(s) to notification list.\n");
/* add all contacts that belong to contactgroups for this escalation */
for(temp_contactgroupsmember = temp_he->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact group '%s' for host escalation to notification list.\n", temp_contactgroupsmember->group_name);
if((temp_contactgroup = temp_contactgroupsmember->group_ptr) == NULL)
continue;
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);
}
}
}
}
/* use normal, non-escalated contacts for this notification */
if(escalate_notification == FALSE || (options & NOTIFICATION_OPTION_BROADCAST)) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Adding normal contacts for host to notification list.\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding individual contacts for host to notification list.\n");
/* add all individual contacts for this host */
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);
}
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact groups for host to notification list.\n");
/* add all contacts that belong to contactgroups for this host */
for(temp_contactgroupsmember = hst->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact group '%s' for host to notification list.\n", temp_contactgroupsmember->group_name);
if((temp_contactgroup = temp_contactgroupsmember->group_ptr) == NULL)
continue;
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);
}
}
}
return OK;
}
/******************************************************************/
/***************** NOTIFICATION TIMING FUNCTIONS ******************/
/******************************************************************/
/* calculates next acceptable re-notification time for a service */
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;
int have_escalated_interval = FALSE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "get_next_service_notification_time()\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Calculating next valid notification time...\n");
/* default notification interval */
interval_to_use = svc->notification_interval;
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) {
/* interval < 0 means to use non-escalated interval */
if(temp_se->notification_interval < 0.0)
continue;
/* skip this entry if it isn't appropriate */
if(is_valid_escalation_for_service_notification(svc, temp_se, NOTIFICATION_OPTION_NONE) == FALSE)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Found a valid escalation w/ interval of %f\n", temp_se->notification_interval);
/* if we haven't used a notification interval from an escalation yet, use this one */
if(have_escalated_interval == FALSE) {
have_escalated_interval = TRUE;
interval_to_use = temp_se->notification_interval;
}
/* else use the shortest of all valid escalation intervals */
else if(temp_se->notification_interval < interval_to_use)
interval_to_use = temp_se->notification_interval;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "New interval: %f\n", interval_to_use);
}
/* if notification interval is 0, we shouldn't send any more problem notifications (unless service is volatile) */
if(interval_to_use == 0.0 && svc->is_volatile == FALSE)
svc->no_more_notifications = TRUE;
else
svc->no_more_notifications = FALSE;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Interval used for calculating next valid notification time: %f\n", interval_to_use);
/* calculate next notification time */
next_notification = offset + (interval_to_use * interval_length);
return next_notification;
}
/* calculates next acceptable re-notification time for a host */
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;
int have_escalated_interval = FALSE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "get_next_host_notification_time()\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Calculating next valid notification time...\n");
/* default notification interval */
interval_to_use = hst->notification_interval;
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) {
/* interval < 0 means to use non-escalated interval */
if(temp_he->notification_interval < 0.0)
continue;
/* skip this entry if it isn't appropriate */
if(is_valid_escalation_for_host_notification(hst, temp_he, NOTIFICATION_OPTION_NONE) == FALSE)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Found a valid escalation w/ interval of %f\n", temp_he->notification_interval);
/* if we haven't used a notification interval from an escalation yet, use this one */
if(have_escalated_interval == FALSE) {
have_escalated_interval = TRUE;
interval_to_use = temp_he->notification_interval;
}
/* else use the shortest of all valid escalation intervals */
else if(temp_he->notification_interval < interval_to_use)
interval_to_use = temp_he->notification_interval;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "New interval: %f\n", interval_to_use);
}
/* if interval is 0, no more notifications should be sent */
if(interval_to_use == 0.0)
hst->no_more_notifications = TRUE;
else
hst->no_more_notifications = FALSE;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Interval used for calculating next valid notification time: %f\n", interval_to_use);
/* calculate next notification time */
next_notification = offset + (interval_to_use * interval_length);
return next_notification;
}
/******************************************************************/
/***************** NOTIFICATION OBJECT FUNCTIONS ******************/
/******************************************************************/
/* given a contact name, find the notification entry for them for the list in memory */
notification * find_notification(contact *cntct) {
notification *temp_notification = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "find_notification() start\n");
if(cntct == NULL)
return NULL;
for(temp_notification = notification_list; temp_notification != NULL; temp_notification = temp_notification->next) {
if(temp_notification->contact == cntct)
return temp_notification;
}
/* we couldn't find the contact in the notification list */
return NULL;
}
/* add a new notification to the list in memory */
int add_notification(nagios_macros *mac, contact *cntct) {
notification *new_notification = NULL;
notification *temp_notification = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "add_notification() start\n");
if(cntct == NULL)
return ERROR;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding contact '%s' to notification list.\n", cntct->name);
/* don't add anything if this contact is already on the notification list */
if((temp_notification = find_notification(cntct)) != NULL)
return OK;
/* allocate memory for a new contact in the notification list */
if((new_notification = malloc(sizeof(notification))) == NULL)
return ERROR;
/* fill in the contact info */
new_notification->contact = cntct;
/* add new notification to head of list */
new_notification->next = notification_list;
notification_list = new_notification;
/* add contact to notification recipients macro */
if(mac->x[MACRO_NOTIFICATIONRECIPIENTS] == NULL)
mac->x[MACRO_NOTIFICATIONRECIPIENTS] = (char *)strdup(cntct->name);
else {
if((mac->x[MACRO_NOTIFICATIONRECIPIENTS] = (char *)realloc(mac->x[MACRO_NOTIFICATIONRECIPIENTS], strlen(mac->x[MACRO_NOTIFICATIONRECIPIENTS]) + strlen(cntct->name) + 2))) {
strcat(mac->x[MACRO_NOTIFICATIONRECIPIENTS], ",");
strcat(mac->x[MACRO_NOTIFICATIONRECIPIENTS], cntct->name);
}
}
return OK;
}
nagios/base/perfdata.c 0000664 0000000 0000000 00000005720 12210155146 0015203 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* PERFDATA.C - Performance data routines for Nagios
*
* Copyright (c) 2000-2004 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 11-29-2004
*
* 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/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;
/******************************************************************/
/************** INITIALIZATION & CLEANUP FUNCTIONS ****************/
/******************************************************************/
/* initializes performance data */
int initialize_performance_data(char *config_file) {
#ifdef USE_XPDDEFAULT
xpddefault_initialize_performance_data(config_file);
#endif
return OK;
}
/* cleans up performance data */
int cleanup_performance_data(char *config_file) {
#ifdef USE_XPDDEFAULT
xpddefault_cleanup_performance_data(config_file);
#endif
return OK;
}
/******************************************************************/
/****************** PERFORMANCE DATA FUNCTIONS ********************/
/******************************************************************/
/* updates service performance data */
int update_service_performance_data(service *svc) {
/* should we be processing performance data for anything? */
if(process_performance_data == FALSE)
return OK;
/* should we process performance data for this service? */
if(svc->process_performance_data == FALSE)
return OK;
/* process the performance data! */
#ifdef USE_XPDDEFAULT
xpddefault_update_service_performance_data(svc);
#endif
return OK;
}
/* updates host performance data */
int update_host_performance_data(host *hst) {
/* should we be processing performance data for anything? */
if(process_performance_data == FALSE)
return OK;
/* should we process performance data for this host? */
if(hst->process_performance_data == FALSE)
return OK;
/* process the performance data! */
#ifdef USE_XPDDEFAULT
xpddefault_update_host_performance_data(hst);
#endif
return OK;
}
nagios/base/sehandlers.c 0000664 0000000 0000000 00000055617 12210155146 0015557 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* 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:
*
* 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/comments.h"
#include "../include/common.h"
#include "../include/statusdata.h"
#include "../include/downtime.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/perfdata.h"
#include "../include/broker.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 *************/
/******************************************************************/
/* handles service check results in an obsessive compulsive manner... */
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;
log_debug_info(DEBUGL_FUNCTIONS, 0, "obsessive_compulsive_service_check_processor()\n");
if(svc == NULL)
return ERROR;
/* bail out if we shouldn't be obsessing */
if(obsess_over_services == FALSE)
return OK;
if(svc->obsess_over_service == FALSE)
return OK;
/* if there is no valid command, exit */
if(ocsp_command == NULL)
return ERROR;
/* find the associated host */
if((temp_host = (host *)svc->host_ptr) == NULL)
return ERROR;
/* update service macros */
memset(&mac, 0, sizeof(mac));
grab_host_macros_r(&mac, temp_host);
grab_service_macros_r(&mac, svc);
/* get the raw command line */
get_raw_command_line_r(&mac, ocsp_command_ptr, ocsp_command, &raw_command, macro_options);
if(raw_command == NULL) {
clear_volatile_macros_r(&mac);
return ERROR;
}
log_debug_info(DEBUGL_CHECKS, 2, "Raw obsessive compulsive service processor command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(&mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL) {
clear_volatile_macros_r(&mac);
return ERROR;
}
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);
/* free memory */
my_free(processed_command);
return OK;
}
/* handles host check results in an obsessive compulsive manner... */
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;
log_debug_info(DEBUGL_FUNCTIONS, 0, "obsessive_compulsive_host_check_processor()\n");
if(hst == NULL)
return ERROR;
/* bail out if we shouldn't be obsessing */
if(obsess_over_hosts == FALSE)
return OK;
if(hst->obsess_over_host == FALSE)
return OK;
/* if there is no valid command, exit */
if(ochp_command == NULL)
return ERROR;
/* update macros */
memset(&mac, 0, sizeof(mac));
grab_host_macros_r(&mac, hst);
/* get the raw command line */
get_raw_command_line_r(&mac, ochp_command_ptr, ochp_command, &raw_command, macro_options);
if(raw_command == NULL) {
clear_volatile_macros_r(&mac);
return ERROR;
}
log_debug_info(DEBUGL_CHECKS, 2, "Raw obsessive compulsive host processor command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(&mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL) {
clear_volatile_macros_r(&mac);
return ERROR;
}
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);
/* free memory */
my_free(processed_command);
return OK;
}
/******************************************************************/
/**************** SERVICE EVENT HANDLER FUNCTIONS *****************/
/******************************************************************/
/* handles changes in the state of a service */
int handle_service_event(service *svc) {
host *temp_host = NULL;
nagios_macros mac;
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_service_event()\n");
if(svc == NULL)
return ERROR;
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_statechange_data(NEBTYPE_STATECHANGE_END, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_STATECHANGE, (void *)svc, svc->current_state, svc->state_type, svc->current_attempt, svc->max_attempts, NULL);
#endif
/* bail out if we shouldn't be running event handlers */
if(enable_event_handlers == FALSE)
return OK;
if(svc->event_handler_enabled == FALSE)
return OK;
/* find the host */
if((temp_host = (host *)svc->host_ptr) == NULL)
return ERROR;
/* update service macros */
memset(&mac, 0, sizeof(mac));
grab_host_macros_r(&mac, temp_host);
grab_service_macros_r(&mac, svc);
/* run the global service event handler */
run_global_service_event_handler(&mac, svc);
/* run the event handler command if there is one */
if(svc->event_handler != NULL)
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;
}
/* runs the global service event handler */
int run_global_service_event_handler(nagios_macros *mac, service *svc) {
char *raw_command = NULL;
char *processed_command = NULL;
char *raw_logentry = NULL;
char *processed_logentry = NULL;
char *command_output = NULL;
int early_timeout = FALSE;
double exectime = 0.0;
int result = 0;
#ifdef USE_EVENT_BROKER
struct timeval start_time;
struct timeval end_time;
int neb_result = OK;
#endif
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_global_service_event_handler()\n");
if(svc == NULL)
return ERROR;
/* bail out if we shouldn't be running event handlers */
if(enable_event_handlers == FALSE)
return OK;
/* a global service event handler command has not been defined */
if(global_service_event_handler == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 1, "Running global event handler for service '%s' on host '%s'...\n", svc->description, svc->host_name);
#ifdef USE_EVENT_BROKER
/* get start time */
gettimeofday(&start_time, NULL);
#endif
/* get the raw command line */
get_raw_command_line_r(mac, global_service_event_handler_ptr, global_service_event_handler, &raw_command, macro_options);
if(raw_command == NULL) {
return ERROR;
}
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Raw global service event handler command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Processed global service event handler command line: %s\n", processed_command);
if(log_event_handlers == TRUE) {
asprintf(&raw_logentry, "GLOBAL SERVICE EVENT HANDLER: %s;%s;$SERVICESTATE$;$SERVICESTATETYPE$;$SERVICEATTEMPT$;%s\n", svc->host_name, svc->description, global_service_event_handler);
process_macros_r(mac, raw_logentry, &processed_logentry, macro_options);
logit(NSLOG_EVENT_HANDLER, FALSE, "%s", processed_logentry);
}
#ifdef USE_EVENT_BROKER
/* send event data to broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_event_handler(NEBTYPE_EVENTHANDLER_START, NEBFLAG_NONE, NEBATTR_NONE, GLOBAL_SERVICE_EVENTHANDLER, (void *)svc, svc->current_state, svc->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, global_service_event_handler, processed_command, NULL, NULL);
/* neb module wants to override (or cancel) the event handler - perhaps it will run the eventhandler itself */
if(neb_result == NEBERROR_CALLBACKOVERRIDE) {
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
#endif
/* run the command */
result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0);
/* check to see if the event handler timed out */
if(early_timeout == TRUE)
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Global service event handler command '%s' timed out after %d seconds\n", processed_command, event_handler_timeout);
#ifdef USE_EVENT_BROKER
/* get end time */
gettimeofday(&end_time, NULL);
#endif
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_event_handler(NEBTYPE_EVENTHANDLER_END, NEBFLAG_NONE, NEBATTR_NONE, GLOBAL_SERVICE_EVENTHANDLER, (void *)svc, svc->current_state, svc->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, global_service_event_handler, processed_command, command_output, NULL);
#endif
/* free memory */
my_free(command_output);
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
/* runs a service event handler command */
int run_service_event_handler(nagios_macros *mac, service *svc) {
char *raw_command = NULL;
char *processed_command = NULL;
char *raw_logentry = NULL;
char *processed_logentry = NULL;
char *command_output = NULL;
int early_timeout = FALSE;
double exectime = 0.0;
int result = 0;
#ifdef USE_EVENT_BROKER
struct timeval start_time;
struct timeval end_time;
int neb_result = OK;
#endif
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_service_event_handler()\n");
if(svc == NULL)
return ERROR;
/* bail if there's no command */
if(svc->event_handler == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 1, "Running event handler for service '%s' on host '%s'...\n", svc->description, svc->host_name);
#ifdef USE_EVENT_BROKER
/* get start time */
gettimeofday(&start_time, NULL);
#endif
/* get the raw command line */
get_raw_command_line_r(mac, svc->event_handler_ptr, svc->event_handler, &raw_command, macro_options);
if(raw_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Raw service event handler command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Processed service event handler command line: %s\n", processed_command);
if(log_event_handlers == TRUE) {
asprintf(&raw_logentry, "SERVICE EVENT HANDLER: %s;%s;$SERVICESTATE$;$SERVICESTATETYPE$;$SERVICEATTEMPT$;%s\n", svc->host_name, svc->description, svc->event_handler);
process_macros_r(mac, raw_logentry, &processed_logentry, macro_options);
logit(NSLOG_EVENT_HANDLER, FALSE, "%s", processed_logentry);
}
#ifdef USE_EVENT_BROKER
/* send event data to broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_event_handler(NEBTYPE_EVENTHANDLER_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_EVENTHANDLER, (void *)svc, svc->current_state, svc->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, svc->event_handler, processed_command, NULL, NULL);
/* neb module wants to override (or cancel) the event handler - perhaps it will run the eventhandler itself */
if(neb_result == NEBERROR_CALLBACKOVERRIDE) {
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
#endif
/* run the command */
result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0);
/* check to see if the event handler timed out */
if(early_timeout == TRUE)
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Service event handler command '%s' timed out after %d seconds\n", processed_command, event_handler_timeout);
#ifdef USE_EVENT_BROKER
/* get end time */
gettimeofday(&end_time, NULL);
#endif
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_event_handler(NEBTYPE_EVENTHANDLER_END, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_EVENTHANDLER, (void *)svc, svc->current_state, svc->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, svc->event_handler, processed_command, command_output, NULL);
#endif
/* free memory */
my_free(command_output);
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
/******************************************************************/
/****************** HOST EVENT HANDLER FUNCTIONS ******************/
/******************************************************************/
/* handles a change in the status of a host */
int handle_host_event(host *hst) {
nagios_macros mac;
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_host_event()\n");
if(hst == NULL)
return ERROR;
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_statechange_data(NEBTYPE_STATECHANGE_END, NEBFLAG_NONE, NEBATTR_NONE, HOST_STATECHANGE, (void *)hst, hst->current_state, hst->state_type, hst->current_attempt, hst->max_attempts, NULL);
#endif
/* bail out if we shouldn't be running event handlers */
if(enable_event_handlers == FALSE)
return OK;
if(hst->event_handler_enabled == FALSE)
return OK;
/* update host macros */
memset(&mac, 0, sizeof(mac));
grab_host_macros_r(&mac, hst);
/* run the global host event handler */
run_global_host_event_handler(&mac, hst);
/* run the event handler command if there is one */
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;
}
/* runs the global host event handler */
int run_global_host_event_handler(nagios_macros *mac, host *hst) {
char *raw_command = NULL;
char *processed_command = NULL;
char *raw_logentry = NULL;
char *processed_logentry = NULL;
char *command_output = NULL;
int early_timeout = FALSE;
double exectime = 0.0;
int result = 0;
#ifdef USE_EVENT_BROKER
struct timeval start_time;
struct timeval end_time;
int neb_result = OK;
#endif
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_global_host_event_handler()\n");
if(hst == NULL)
return ERROR;
/* bail out if we shouldn't be running event handlers */
if(enable_event_handlers == FALSE)
return OK;
/* no global host event handler command is defined */
if(global_host_event_handler == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 1, "Running global event handler for host '%s'..\n", hst->name);
#ifdef USE_EVENT_BROKER
/* get start time */
gettimeofday(&start_time, NULL);
#endif
/* get the raw command line */
get_raw_command_line_r(mac, global_host_event_handler_ptr, global_host_event_handler, &raw_command, macro_options);
if(raw_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Raw global host event handler command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Processed global host event handler command line: %s\n", processed_command);
if(log_event_handlers == TRUE) {
asprintf(&raw_logentry, "GLOBAL HOST EVENT HANDLER: %s;$HOSTSTATE$;$HOSTSTATETYPE$;$HOSTATTEMPT$;%s\n", hst->name, global_host_event_handler);
process_macros_r(mac, raw_logentry, &processed_logentry, macro_options);
logit(NSLOG_EVENT_HANDLER, FALSE, "%s", processed_logentry);
}
#ifdef USE_EVENT_BROKER
/* send event data to broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_event_handler(NEBTYPE_EVENTHANDLER_START, NEBFLAG_NONE, NEBATTR_NONE, GLOBAL_HOST_EVENTHANDLER, (void *)hst, hst->current_state, hst->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, global_host_event_handler, processed_command, NULL, NULL);
/* neb module wants to override (or cancel) the event handler - perhaps it will run the eventhandler itself */
if(neb_result == NEBERROR_CALLBACKOVERRIDE) {
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
#endif
/* run the command */
result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0);
/* check for a timeout in the execution of the event handler command */
if(early_timeout == TRUE)
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Global host event handler command '%s' timed out after %d seconds\n", processed_command, event_handler_timeout);
#ifdef USE_EVENT_BROKER
/* get end time */
gettimeofday(&end_time, NULL);
#endif
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_event_handler(NEBTYPE_EVENTHANDLER_END, NEBFLAG_NONE, NEBATTR_NONE, GLOBAL_HOST_EVENTHANDLER, (void *)hst, hst->current_state, hst->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, global_host_event_handler, processed_command, command_output, NULL);
#endif
/* free memory */
my_free(command_output);
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
/* runs a host event handler command */
int run_host_event_handler(nagios_macros *mac, host *hst) {
char *raw_command = NULL;
char *processed_command = NULL;
char *raw_logentry = NULL;
char *processed_logentry = NULL;
char *command_output = NULL;
int early_timeout = FALSE;
double exectime = 0.0;
int result = 0;
#ifdef USE_EVENT_BROKER
struct timeval start_time;
struct timeval end_time;
int neb_result = OK;
#endif
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_host_event_handler()\n");
if(hst == NULL)
return ERROR;
/* bail if there's no command */
if(hst->event_handler == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 1, "Running event handler for host '%s'..\n", hst->name);
#ifdef USE_EVENT_BROKER
/* get start time */
gettimeofday(&start_time, NULL);
#endif
/* get the raw command line */
get_raw_command_line_r(mac, hst->event_handler_ptr, hst->event_handler, &raw_command, macro_options);
if(raw_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Raw host event handler command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Processed host event handler command line: %s\n", processed_command);
if(log_event_handlers == TRUE) {
asprintf(&raw_logentry, "HOST EVENT HANDLER: %s;$HOSTSTATE$;$HOSTSTATETYPE$;$HOSTATTEMPT$;%s\n", hst->name, hst->event_handler);
process_macros_r(mac, raw_logentry, &processed_logentry, macro_options);
logit(NSLOG_EVENT_HANDLER, FALSE, "%s", processed_logentry);
}
#ifdef USE_EVENT_BROKER
/* send event data to broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_event_handler(NEBTYPE_EVENTHANDLER_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_EVENTHANDLER, (void *)hst, hst->current_state, hst->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, hst->event_handler, processed_command, NULL, NULL);
/* neb module wants to override (or cancel) the event handler - perhaps it will run the eventhandler itself */
if(neb_result == NEBERROR_CALLBACKOVERRIDE) {
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
#endif
/* run the command */
result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0);
/* check to see if the event handler timed out */
if(early_timeout == TRUE)
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Host event handler command '%s' timed out after %d seconds\n", processed_command, event_handler_timeout);
#ifdef USE_EVENT_BROKER
/* get end time */
gettimeofday(&end_time, NULL);
#endif
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_event_handler(NEBTYPE_EVENTHANDLER_END, NEBFLAG_NONE, NEBATTR_NONE, HOST_EVENTHANDLER, (void *)hst, hst->current_state, hst->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, hst->event_handler, processed_command, command_output, NULL);
#endif
/* free memory */
my_free(command_output);
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
nagios/base/sretention.c 0000664 0000000 0000000 00000007104 12210155146 0015605 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* SRETENTION.C - State retention routines for Nagios
*
* Copyright (c) 1999-2006 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 10-18-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.
*
*****************************************************************************/
/*********** COMMON HEADER FILES ***********/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/statusdata.h"
#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
/******************************************************************/
/************* TOP-LEVEL STATE INFORMATION FUNCTIONS **************/
/******************************************************************/
/* 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;
}
/* 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;
}
/* save all host and service state information */
int save_state_information(int autosave) {
int result = OK;
if(retain_state_information == FALSE)
return OK;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
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 */
broker_retention_data(NEBTYPE_RETENTIONDATA_ENDSAVE, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
if(result == ERROR)
return ERROR;
if(autosave == TRUE)
logit(NSLOG_PROCESS_INFO, FALSE, "Auto-save of retention data completed successfully.\n");
return OK;
}
/* reads in initial host and state information */
int read_initial_state_information(void) {
int result = OK;
if(retain_state_information == FALSE)
return OK;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
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 */
broker_retention_data(NEBTYPE_RETENTIONDATA_ENDLOAD, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
if(result == ERROR)
return ERROR;
return OK;
}
nagios/base/utils.c 0000664 0000000 0000000 00000405373 12210155146 0014565 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* UTILS.C - Miscellaneous utility functions for Nagios
*
* Copyright (c) 1999-2009 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 06-16-2009
*
* 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/macros.h"
#include "../include/nagios.h"
#include "../include/netutils.h"
#include "../include/broker.h"
#include "../include/nebmods.h"
#include "../include/nebmodules.h"
#ifdef EMBEDDEDPERL
#include "../include/epn_nagios.h"
static PerlInterpreter *my_perl = NULL;
int use_embedded_perl = TRUE;
#endif
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;
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;
extern char *nagios_user;
extern char *nagios_group;
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;
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;
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 sigshutdown;
extern int sigrestart;
extern char *sigs[35];
extern int caught_signal;
extern int sig_id;
extern int daemon_mode;
extern int daemon_dumps_core;
extern int nagios_pid;
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 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 ocsp_timeout;
extern int ochp_timeout;
extern int log_initial_states;
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 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 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 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 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;
extern unsigned long next_comment_id;
extern unsigned long next_downtime_id;
extern unsigned long next_event_id;
extern unsigned long next_notification_id;
extern int log_rotation_method;
extern time_t program_start;
extern time_t last_command_check;
extern time_t last_command_status_update;
extern time_t last_log_rotation;
extern int verify_config;
extern int test_scheduling;
extern check_result check_result_info;
extern int max_parallel_service_checks;
extern int currently_running_service_checks;
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;
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 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;
/* from GNU defines errno as a macro, since it's a per-thread variable */
#ifndef errno
extern int errno;
#endif
static long long check_file_size(char *, unsigned long, struct rlimit);
/******************************************************************/
/******************** SYSTEM COMMAND FUNCTIONS ********************/
/******************************************************************/
/* executes a system command - used for notifications, event handlers, etc. */
int my_system_r(nagios_macros *mac, char *cmd, int timeout, int *early_timeout, double *exectime, char **output, int max_output_length) {
pid_t pid = 0;
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;
struct timeval start_time, end_time;
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;
#endif
dSP;
#endif
log_debug_info(DEBUGL_FUNCTIONS, 0, "my_system_r()\n");
/* initialize return variables */
if(output != NULL)
*output = NULL;
*early_timeout = FALSE;
*exectime = 0.0;
/* if no command was passed, return with no error */
if(cmd == NULL)
return STATE_OK;
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);
/* make the pipe non-blocking */
fcntl(fd[0], F_SETFL, O_NONBLOCK);
fcntl(fd[1], F_SETFL, O_NONBLOCK);
/* get the command start time */
gettimeofday(&start_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
broker_system_command(NEBTYPE_SYSTEM_COMMAND_START, NEBFLAG_NONE, NEBATTR_NONE, start_time, end_time, *exectime, timeout, *early_timeout, result, cmd, NULL, NULL);
#endif
/* fork */
pid = fork();
/* 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);
/* close both ends of the pipe */
close(fd[0]);
close(fd[1]);
return STATE_UNKNOWN;
}
/* execute the command in the child process */
if(pid == 0) {
/* become process group leader */
setpgid(0, 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();
/* reset signal handling */
reset_sighandler();
/* close pipe for reading */
close(fd[0]);
/* prevent fd from being inherited by child processed */
flags = fcntl(fd[1], F_GETFD, 0);
flags |= FD_CLOEXEC;
fcntl(fd[1], F_SETFD, flags);
/* trap commands that timeout */
signal(SIGALRM, my_system_sighandler);
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");
/* report an error if we couldn't run the command */
if(fp == NULL) {
strncpy(buffer, "(Error: Could not execute command)\n", sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\x0';
/* write the error back to the parent process */
write(fd[1], buffer, strlen(buffer) + 1);
result = STATE_CRITICAL;
}
else {
/* write all the lines of output back to the parent process */
while(fgets(buffer, sizeof(buffer) - 1, fp))
write(fd[1], buffer, strlen(buffer));
/* close the command and get termination status */
status = pclose(fp);
/* report an error if we couldn't close the command */
if(status == -1)
result = STATE_CRITICAL;
else {
if(WEXITSTATUS(status) == 0 && WIFSIGNALED(status))
result = 128 + WTERMSIG(status);
result = WEXITSTATUS(status);
}
}
/* close pipe for writing */
close(fd[1]);
/* reset the alarm */
alarm(0);
/* clear environment variables */
set_all_macro_environment_vars_r(mac, FALSE);
#ifndef DONT_USE_MEMORY_PERFORMANCE_TWEAKS
/* 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);
#endif
_exit(result);
}
/* parent waits for child to finish executing command */
else {
/* close pipe for writing */
close(fd[1]);
/* wait for child to exit */
waitpid(pid, &status, 0);
/* get the end time for running the command */
gettimeofday(&end_time, NULL);
/* return execution time in milliseconds */
*exectime = (double)((double)(end_time.tv_sec - start_time.tv_sec) + (double)((end_time.tv_usec - start_time.tv_usec) / 1000) / 1000.0);
if(*exectime < 0.0)
*exectime = 0.0;
/* get the exit code returned from the program */
result = WEXITSTATUS(status);
/* 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);
}
/* check bounds on the return value */
if(result < -1 || result > 3)
result = STATE_UNKNOWN;
/* initialize dynamic buffer */
dbuf_init(&output_dbuf, dbuf_chunk);
/* Opsera patch to check timeout before attempting to read output via pipe. Originally by Sven Nierlein */
/* if there was a critical return code AND the command time exceeded the timeout thresholds, assume a timeout */
if(result == STATE_CRITICAL && (end_time.tv_sec - start_time.tv_sec) >= timeout) {
/* set the early timeout flag */
*early_timeout = TRUE;
/* try to kill the command that timed out by sending termination signal to child process group */
kill((pid_t)(-pid), SIGTERM);
sleep(1);
kill((pid_t)(-pid), SIGKILL);
}
/* read output if timeout has not occurred */
else {
/* initialize output */
strcpy(buffer, "");
/* try and read the results from the command output (retry if we encountered a signal) */
do {
bytes_read = read(fd[0], buffer, sizeof(buffer) - 1);
/* append data we just read to dynamic buffer */
if(bytes_read > 0) {
buffer[bytes_read] = '\x0';
dbuf_strcat(&output_dbuf, buffer);
}
/* handle errors */
if(bytes_read == -1) {
/* we encountered a recoverable error, so try again */
if(errno == EINTR)
continue;
/* patch by Henning Brauer to prevent CPU hogging */
else if(errno == EAGAIN) {
struct pollfd pfd;
pfd.fd = fd[0];
pfd.events = POLLIN;
poll(&pfd, 1, -1);
continue;
}
else
break;
}
/* we're done */
if(bytes_read == 0)
break;
}
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)
output_dbuf.buf[max_output_length] = '\x0';
if(output != NULL && output_dbuf.buf)
*output = (char *)strdup(output_dbuf.buf);
}
log_debug_info(DEBUGL_COMMANDS, 1, "Execution time=%.3f sec, early timeout=%d, result=%d, output=%s\n", *exectime, *early_timeout, result, (output_dbuf.buf == NULL) ? "(null)" : output_dbuf.buf);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_system_command(NEBTYPE_SYSTEM_COMMAND_END, NEBFLAG_NONE, NEBATTR_NONE, start_time, end_time, *exectime, timeout, *early_timeout, result, cmd, (output_dbuf.buf == NULL) ? NULL : output_dbuf.buf, NULL);
#endif
/* free memory */
dbuf_free(&output_dbuf);
/* close the pipe for reading */
close(fd[0]);
}
return result;
}
/*
* For API compatibility, we must include a my_system() whose
* signature doesn't include the nagios_macros variable.
* NDOUtils uses this. Possibly other modules as well.
*/
int my_system(char *cmd, int timeout, int *early_timeout, double *exectime, char **output, int max_output_length) {
return my_system_r(get_global_macros(), cmd, timeout, early_timeout, exectime, output, max_output_length);
}
/* given a "raw" command, return the "expanded" or "whole" command line */
int get_raw_command_line_r(nagios_macros *mac, command *cmd_ptr, char *cmd, char **full_command, int macro_options) {
char temp_arg[MAX_COMMAND_BUFFER] = "";
char *arg_buffer = NULL;
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");
/* clear the argv macros */
clear_argv_macros_r(mac);
/* make sure we've got all the requirements */
if(cmd_ptr == NULL || full_command == NULL)
return ERROR;
log_debug_info(DEBUGL_COMMANDS | DEBUGL_CHECKS | DEBUGL_MACROS, 2, "Raw Command Input: %s\n", cmd_ptr->command_line);
/* get the full command line */
*full_command = (char *)strdup((cmd_ptr->command_line == NULL) ? "" : cmd_ptr->command_line);
/* XXX: Crazy indent */
/* get the command arguments */
if(cmd != NULL) {
/* skip the command name (we're about to get the arguments)... */
for(arg_index = 0;; arg_index++) {
if(cmd[arg_index] == '!' || cmd[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[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 < 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')
break;
/* normal of escaped char */
temp_arg[y] = cmd[arg_index];
y++;
/* clear escaped flag */
escaped = FALSE;
}
temp_arg[y] = '\x0';
/* ADDED 01/29/04 EG */
/* process any macros we find in the argument */
process_macros_r(mac, temp_arg, &arg_buffer, macro_options);
mac->argv[x] = arg_buffer;
}
}
log_debug_info(DEBUGL_COMMANDS | DEBUGL_CHECKS | DEBUGL_MACROS, 2, "Expanded Command Output: %s\n", *full_command);
return OK;
}
/*
* This function modifies the global macro struct and is thus not
* threadsafe
*/
int get_raw_command_line(command *cmd_ptr, char *cmd, char **full_command, int macro_options) {
nagios_macros *mac;
mac = get_global_macros();
return get_raw_command_line_r(mac, cmd_ptr, cmd, full_command, macro_options);
}
/******************************************************************/
/******************** ENVIRONMENT FUNCTIONS ***********************/
/******************************************************************/
/* sets or unsets an environment variable */
int set_environment_var(char *name, char *value, int set) {
#ifndef HAVE_SETENV
char *env_string = NULL;
#endif
/* we won't mess with null variable names */
if(name == NULL)
return ERROR;
/* set the environment variable */
if(set == TRUE) {
#ifdef HAVE_SETENV
setenv(name, (value == NULL) ? "" : value, 1);
#else
/* needed for Solaris and systems that don't have setenv() */
/* this will leak memory, but in a "controlled" way, since lost memory should be freed when the child process exits */
asprintf(&env_string, "%s=%s", name, (value == NULL) ? "" : value);
if(env_string)
putenv(env_string);
#endif
}
/* clear the variable */
else {
#ifdef HAVE_UNSETENV
unsetenv(name);
#endif
}
return OK;
}
/******************************************************************/
/************************* TIME FUNCTIONS *************************/
/******************************************************************/
/* Checks if the given time is in daylight time saving period */
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) {
int shift = 0, dst_end, dst_start;
dst_start = is_dst_time(start);
dst_end = is_dst_time(end);
if(dst_start < dst_end) {
shift = 3600;
}
else if(dst_start > dst_end) {
shift = -3600;
}
return shift;
}
/*#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;
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;
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");
/* if no period was specified, assume the time is good */
if(tperiod == NULL)
return OK;
/* 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 */
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
midnight = mktime(t);
/**** check exceptions first ****/
for(daterange_type = 0; daterange_type < DATERANGE_TYPES; daterange_type++) {
for(temp_daterange = tperiod->exceptions[daterange_type]; temp_daterange != NULL; temp_daterange = temp_daterange->next) {
#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));
#endif
/* get the start time */
switch(daterange_type) {
case DATERANGE_CALENDAR_DATE:
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
t->tm_wday = 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:
start_time = calculate_time_from_day_of_month(test_time_year, temp_daterange->smon, temp_daterange->smday);
break;
case DATERANGE_MONTH_DAY:
start_time = calculate_time_from_day_of_month(test_time_year, test_time_mon, temp_daterange->smday);
break;
case DATERANGE_MONTH_WEEK_DAY:
start_time = calculate_time_from_weekday_of_month(test_time_year, temp_daterange->smon, temp_daterange->swday, temp_daterange->swday_offset);
break;
case DATERANGE_WEEK_DAY:
start_time = calculate_time_from_weekday_of_month(test_time_year, test_time_mon, temp_daterange->swday, temp_daterange->swday_offset);
break;
default:
continue;
break;
}
/* 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_wday = 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:
year = test_time_year;
end_time = calculate_time_from_day_of_month(year, temp_daterange->emon, temp_daterange->emday);
/* advance a year if necessary: august 2 - february 5 */
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:
end_time = calculate_time_from_day_of_month(test_time_year, test_time_mon, temp_daterange->emday);
break;
case DATERANGE_MONTH_WEEK_DAY:
year = test_time_year;
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:
end_time = calculate_time_from_weekday_of_month(test_time_year, test_time_mon, temp_daterange->ewday, temp_daterange->ewday_offset);
break;
default:
continue;
break;
}
#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));
#endif
/* start date was bad, so skip this date range */
if((unsigned long)start_time == 0L)
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 */
/* use same year calculated above */
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(test_time_year, test_time_mon, -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 */
/* use same year calculated above */
end_time = calculate_time_from_day_of_month(year, test_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(test_time_year, test_time_mon, -1);
break;
default:
continue;
break;
}
}
/* calculate skip date start (and end) */
if(temp_daterange->skip_interval > 1) {
/* skip start date must be before test time */
if(start_time > test_time)
continue;
/* 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 test time? */
days = (shift + (unsigned long)midnight - (unsigned long)start_time) / (3600 * 24);
/* if test date doesn't fall on a skip interval day, bail out early */
if((days % temp_daterange->skip_interval) != 0)
continue;
/* use midnight of test date as start time */
else
start_time = midnight;
/* if skipping range has no end, use test date as end */
if((daterange_type == DATERANGE_CALENDAR_DATE) && (is_daterange_single_day(temp_daterange) == TRUE))
end_time = midnight;
}
#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("%d DAYS PASSED\n", days);
printf("DLST SHIFT: %d", 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) {
#ifdef TEST_TIMEPERIODS_A
printf("0 MINUTE RANGE EXCLUSION\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;
}
}
}
/**** check normal, weekly rotating schedule last ****/
/* check weekday time ranges */
for(temp_timerange = tperiod->days[test_time_wday]; 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;
}
/*#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;
struct tm *t, tm_s;
time_t day_start = (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(tperiod == NULL) {
*valid_time = preferred_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;
}
/* 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);
/* 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;
/* 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)
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;
}
}
#ifdef TEST_TIMEPERIODS_B
printf("ENDTIME2: %lu = %s", (unsigned long)end_time, ctime(&end_time));
#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;
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);
#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 < 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
}
}
}
}
}
/**** find next available time from normal, weekly rotating schedule (in this timeperiod definition) ****/
/* 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++) {
/* break out of the loop if we have checked an entire week already */
if(has_looped == TRUE && weekday >= pref_time_wday)
break;
if(weekday >= 7) {
weekday -= 7;
has_looped = 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 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 */
else
*valid_time = earliest_time;
return;
}
/* given a preferred time, get the next valid time within a time period */
void get_next_valid_time(time_t pref_time, time_t *valid_time, timeperiod *tperiod) {
time_t current_time = (time_t)0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "get_next_valid_time()\n");
/* 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);
}
/* tests if a date range covers just a single day */
int is_daterange_single_day(daterange *dr) {
if(dr == NULL)
return FALSE;
if(dr->syear != dr->eyear)
return FALSE;
if(dr->smon != dr->emon)
return FALSE;
if(dr->smday != dr->emday)
return FALSE;
if(dr->swday != dr->ewday)
return FALSE;
if(dr->swday_offset != dr->ewday_offset)
return FALSE;
return TRUE;
}
/* returns a time (midnight) of particular (3rd, last) day in a given month */
time_t calculate_time_from_day_of_month(int year, int month, int monthday) {
time_t midnight;
int day = 0;
struct tm t;
#ifdef TEST_TIMEPERIODS
printf("YEAR: %d, MON: %d, MDAY: %d\n", year, month, monthday);
#endif
/* positive day (3rd day) */
if(monthday > 0) {
t.tm_sec = 0;
t.tm_min = 0;
t.tm_hour = 0;
t.tm_year = year;
t.tm_mon = month;
t.tm_mday = monthday;
t.tm_isdst = -1;
midnight = mktime(&t);
#ifdef TEST_TIMEPERIODS
printf("MIDNIGHT CALC: %s", ctime(&midnight));
#endif
/* if we rolled over to the next month, time is invalid */
/* assume the user's intention is to keep it in the current month */
if(t.tm_mon != month)
midnight = (time_t)0L;
}
/* negative offset (last day, 3rd to last day) */
else {
/* find last day in the month */
day = 32;
do {
/* back up a day */
day--;
/* make the new time */
t.tm_mon = month;
t.tm_year = year;
t.tm_mday = day;
t.tm_isdst = -1;
midnight = mktime(&t);
}
while(t.tm_mon != month);
/* now that we know the last day, back up more */
/* make the new time */
t.tm_mon = month;
t.tm_year = year;
/* -1 means last day of month, so add one to to make this correct - Mike Bird */
t.tm_mday += (monthday < -30) ? -30 : monthday + 1;
t.tm_isdst = -1;
midnight = mktime(&t);
/* if we rolled over to the previous month, time is invalid */
/* assume the user's intention is to keep it in the current month */
if(t.tm_mon != month)
midnight = (time_t)0L;
}
return midnight;
}
/* returns a time (midnight) of particular (3rd, last) weekday in a given month */
time_t calculate_time_from_weekday_of_month(int year, int month, int weekday, int weekday_offset) {
time_t midnight;
int days = 0;
int weeks = 0;
struct tm t;
t.tm_sec = 0;
t.tm_min = 0;
t.tm_hour = 0;
t.tm_year = year;
t.tm_mon = month;
t.tm_mday = 1;
t.tm_isdst = -1;
midnight = mktime(&t);
/* how many days must we advance to reach the first instance of the weekday this month? */
days = weekday - (t.tm_wday);
if(days < 0)
days += 7;
/* positive offset (3rd thursday) */
if(weekday_offset > 0) {
/* how many weeks must we advance (no more than 5 possible) */
weeks = (weekday_offset > 5) ? 5 : weekday_offset;
days += ((weeks - 1) * 7);
/* make the new time */
t.tm_mon = month;
t.tm_year = year;
t.tm_mday = days + 1;
t.tm_isdst = -1;
midnight = mktime(&t);
/* if we rolled over to the next month, time is invalid */
/* assume the user's intention is to keep it in the current month */
if(t.tm_mon != month)
midnight = (time_t)0L;
}
/* negative offset (last thursday, 3rd to last tuesday) */
else {
/* find last instance of weekday in the month */
days += (5 * 7);
do {
/* back up a week */
days -= 7;
/* make the new time */
t.tm_mon = month;
t.tm_year = year;
t.tm_mday = days + 1;
t.tm_isdst = -1;
midnight = mktime(&t);
}
while(t.tm_mon != month);
/* now that we know the last instance of the weekday, back up more */
weeks = (weekday_offset < -5) ? -5 : weekday_offset;
days = ((weeks + 1) * 7);
/* make the new time */
t.tm_mon = month;
t.tm_year = year;
t.tm_mday += days;
t.tm_isdst = -1;
midnight = mktime(&t);
/* if we rolled over to the previous month, time is invalid */
/* assume the user's intention is to keep it in the current month */
if(t.tm_mon != month)
midnight = (time_t)0L;
}
return midnight;
}
/* get the next time to schedule a log rotation */
time_t get_next_log_rotation_time(void) {
time_t current_time;
struct tm *t, tm_s;
int is_dst_now = FALSE;
time_t run_time;
time(¤t_time);
t = localtime_r(¤t_time, &tm_s);
t->tm_min = 0;
t->tm_sec = 0;
is_dst_now = (t->tm_isdst > 0) ? TRUE : FALSE;
switch(log_rotation_method) {
case LOG_ROTATION_HOURLY:
t->tm_hour++;
run_time = mktime(t);
break;
case LOG_ROTATION_DAILY:
t->tm_mday++;
t->tm_hour = 0;
run_time = mktime(t);
break;
case LOG_ROTATION_WEEKLY:
t->tm_mday += (7 - t->tm_wday);
t->tm_hour = 0;
run_time = mktime(t);
break;
case LOG_ROTATION_MONTHLY:
default:
t->tm_mon++;
t->tm_mday = 1;
t->tm_hour = 0;
run_time = mktime(t);
break;
}
if(is_dst_now == TRUE && t->tm_isdst == 0)
run_time += 3600;
else if(is_dst_now == FALSE && t->tm_isdst > 0)
run_time -= 3600;
return run_time;
}
/******************************************************************/
/******************** SIGNAL HANDLER FUNCTIONS ********************/
/******************************************************************/
/* trap signals so we can exit gracefully */
void setup_sighandler(void) {
/* reset the shutdown flag */
sigshutdown = FALSE;
/* remove buffering from stderr, stdin, and stdout */
setbuf(stdin, (char *)NULL);
setbuf(stdout, (char *)NULL);
setbuf(stderr, (char *)NULL);
/* initialize signal handling */
signal(SIGPIPE, SIG_IGN);
signal(SIGQUIT, sighandler);
signal(SIGTERM, sighandler);
signal(SIGHUP, sighandler);
if(daemon_dumps_core == FALSE && daemon_mode == TRUE)
signal(SIGSEGV, sighandler);
return;
}
/* reset signal handling... */
void reset_sighandler(void) {
/* set signal handling to default actions */
signal(SIGQUIT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
signal(SIGXFSZ, SIG_DFL);
return;
}
/* handle signals */
void sighandler(int sig) {
int x = 0;
/* if shutdown is already true, we're in a signal trap loop! */
/* changed 09/07/06 to only exit on segfaults */
if(sigshutdown == TRUE && sig == SIGSEGV)
exit(ERROR);
caught_signal = TRUE;
if(sig < 0)
sig = -sig;
for(x = 0; sigs[x] != (char *)NULL; x++);
sig %= x;
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)
sigshutdown = TRUE;
return;
}
/* 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
/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
don't log too often. */
unsigned long log_interval = 300; /* How frequently to log messages
about receiving the signal */
struct rlimit rlim;
time_t now;
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,
};
int x;
char **filep;
long long size;
long long max_size = 0LL;
char *max_name = NULL;
if(SIGXFSZ == sig) { /* Make sure we're handling the correct signal */
/* Check the current time and if less time has passed since the last
time the signal was received, ignore it */
time(&now);
if((unsigned long)(now - lastlog_time) < log_interval) return;
/* Get the current file size limit */
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",
strerror(errno));
}
/* Try to figure out which file caused the signal and react
appropriately */
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) {
lastlog_time = now;
return;
}
else if(size > max_size) {
max_size = size;
max_name = log_file;
}
}
}
/* 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 "
"determine which file may have caused it.");
}
}
return;
}
/* 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
checking the file size */
static long long check_file_size(char *path, unsigned long fudge,
struct rlimit rlim) {
struct stat status;
/* Make sure we were passed a legitimate file path */
if(NULL == path) {
return 0;
}
/* Get the status of the file */
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
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,
(unsigned long long)rlim.rlim_cur);
return -1;
}
else {
return status.st_size;
}
}
else {
return 0;
}
}
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",
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 ************************/
/******************************************************************/
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");
if(daemon_dumps_core == TRUE && homedir != NULL)
chdir(homedir);
else
chdir("/");
umask(S_IWGRP | S_IWOTH);
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());
cleanup();
exit(ERROR);
}
/* 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");
cleanup();
exit(ERROR);
}
/* 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);
cleanup();
exit(ERROR);
}
}
/* check for SIGHUP */
if(val == 1 && (pid = (pid_t)pidno) == getpid()) {
close(lockfile);
return OK;
}
/* exit on errors... */
if((pid = fork()) < 0)
return(ERROR);
/* parent process goes away.. */
else if((int)pid != 0)
exit(OK);
/* child continues... */
/* child becomes session leader... */
setsid();
/* 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(errno == EACCES || errno == EAGAIN) {
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));
cleanup();
exit(ERROR);
}
/* prevent daemon from dumping a core file... */
#ifdef RLIMIT_CORE
if(daemon_dumps_core == FALSE) {
getrlimit(RLIMIT_CORE, &limit);
limit.rlim_cur = 0;
setrlimit(RLIMIT_CORE, &limit);
}
#endif
/* 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);
/* 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);
#endif
return OK;
}
/******************************************************************/
/*********************** SECURITY FUNCTIONS ***********************/
/******************************************************************/
/* drops privileges */
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 = 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());
/* 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 OK;
/* set effective group ID */
if(group != NULL) {
/* see if this is a group name */
if(strspn(group, "0123456789") < strlen(group)) {
grp = (struct group *)getgrnam(group);
if(grp != NULL)
gid = (gid_t)(grp->gr_gid);
else
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not get group entry for '%s'", 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) {
/* see if this is a user name */
if(strspn(user, "0123456789") < strlen(user)) {
pw = (struct passwd *)getpwnam(user);
if(pw != NULL)
uid = (uid_t)(pw->pw_uid);
else
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not get passwd entry for '%s'", 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(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);
result = ERROR;
}
}
log_debug_info(DEBUGL_PROCESS, 0, "New UID/GID: %d/%d\n", (int)getuid(), (int)getgid());
return result;
}
/******************************************************************/
/************************* 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];
DIR *dirp = NULL;
struct dirent *dirfile = NULL;
register int x = 0;
struct stat stat_buf;
struct stat ok_stat_buf;
char *temp_buffer = NULL;
int result = OK;
/* make sure we have what we need */
if(dirname == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: No check result queue 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 result queue directory '%s' for reading.\n", dirname);
return ERROR;
}
log_debug_info(DEBUGL_CHECKS, 1, "Starting to read check result queue '%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 == 7 && dirfile->d_name[0] == 'c') {
if(stat(file, &stat_buf) == -1) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not stat() check result file '%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... */
/* can we find the associated ok-to-go file ? */
asprintf(&temp_buffer, "%s.ok", file);
result = stat(temp_buffer, &ok_stat_buf);
my_free(temp_buffer);
if(result == -1)
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);
/* 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);
}
}
}
closedir(dirp);
return result;
}
/* reads check result(s) from a file */
int process_check_result_file(char *fname, check_result **listp, int delete_file, int need_output) {
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;
if(fname == NULL)
return ERROR;
time(¤t_time);
log_debug_info(DEBUGL_CHECKS, 1, "Processing check result file: '%s'\n", fname);
/* open the file for reading */
if((thefile = mmap_fopen(fname)) == NULL) {
/* try removing the file - zero length files can't be mmap()'ed, so it might exist */
unlink(fname);
return ERROR;
}
/* read in all lines from the file */
while(1) {
/* free memory */
my_free(input);
/* read the next line */
if((input = mmap_fgets_multiline(thefile)) == NULL)
break;
/* skip comments */
if(input[0] == '#')
continue;
/* 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(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 */
else {
free_check_result(new_cr);
init_check_result(new_cr);
new_cr->output_file = (char *)strdup(fname);
}
}
}
if((var = my_strtok(input, "=")) == NULL)
continue;
if((val = my_strtok(NULL, "\n")) == NULL)
continue;
/* found the file time */
if(!strcmp(var, "file_time")) {
/* 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);
else if(!strcmp(var, "service_description")) {
new_cr->service_description = (char *)strdup(val);
new_cr->object_check_type = SERVICE_CHECK;
}
else if(!strcmp(var, "check_type"))
new_cr->check_type = atoi(val);
else if(!strcmp(var, "check_options"))
new_cr->check_options = atoi(val);
else if(!strcmp(var, "scheduled_check"))
new_cr->scheduled_check = atoi(val);
else if(!strcmp(var, "reschedule_check"))
new_cr->reschedule_check = atoi(val);
else if(!strcmp(var, "latency"))
new_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);
}
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);
}
else if(!strcmp(var, "early_timeout"))
new_cr->early_timeout = atoi(val);
else if(!strcmp(var, "exited_ok"))
new_cr->exited_ok = atoi(val);
else if(!strcmp(var, "return_code"))
new_cr->return_code = atoi(val);
else if(!strcmp(var, "output"))
new_cr->output = (char *)strdup(val);
}
}
/* we have something */
if(new_cr) {
/* 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);
}
}
/* 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);
return OK;
}
/* deletes as check result file, as well as its ok-to-go file */
int delete_check_result_file(char *fname) {
char *temp_buffer = NULL;
/* delete the result file */
unlink(fname);
/* delete the ok-to-go file */
asprintf(&temp_buffer, "%s.ok", fname);
unlink(temp_buffer);
my_free(temp_buffer);
return OK;
}
/* 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) {
if(info == NULL)
return ERROR;
/* reset vars */
info->object_check_type = HOST_CHECK;
info->host_name = NULL;
info->service_description = NULL;
info->check_type = HOST_CHECK_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;
info->finish_time.tv_sec = 0;
info->finish_time.tv_usec = 0;
info->early_timeout = FALSE;
info->exited_ok = TRUE;
info->return_code = 0;
info->output = NULL;
info->next = 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) {
if(info == NULL)
return OK;
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 ************************/
/******************************************************************/
/* 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";
int x;
if(buf == NULL || start_index == NULL)
return NULL;
if(bufsize < 0)
return NULL;
if(*start_index >= (bufsize - 1))
return NULL;
sptr = buf + *start_index;
/* end of buffer */
if(sptr[0] == '\x0')
return NULL;
x = strcspn(sptr, nl);
sptr[x] = '\x0';
*start_index += x + 1;
return sptr;
}
/* determines whether or not an object name (host, service, etc) contains illegal characters */
int contains_illegal_object_chars(char *name) {
register int x = 0;
register int y = 0;
register int ch = 0;
if(name == 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++)
if(name[x] == illegal_object_chars[y])
return TRUE;
}
return FALSE;
}
/* escapes newlines in a string */
char *escape_newlines(char *rawbuf) {
char *newbuf = NULL;
register int x, y;
if(rawbuf == NULL)
return NULL;
/* allocate enough memory to escape all chars if necessary */
if((newbuf = malloc((strlen(rawbuf) * 2) + 1)) == NULL)
return NULL;
for(x = 0, y = 0; rawbuf[x] != (char)'\x0'; x++) {
/* escape backslashes */
if(rawbuf[x] == '\\') {
newbuf[y++] = '\\';
newbuf[y++] = '\\';
}
/* escape newlines */
else if(rawbuf[x] == '\n') {
newbuf[y++] = '\\';
newbuf[y++] = 'n';
}
else
newbuf[y++] = rawbuf[x];
}
newbuf[y] = '\x0';
return newbuf;
}
/* compares strings */
int compare_strings(char *val1a, char *val2a) {
/* use the compare_hashdata() function */
return compare_hashdata(val1a, NULL, val2a, NULL);
}
/******************************************************************/
/************************* FILE FUNCTIONS *************************/
/******************************************************************/
/* renames a file - works across filesystems (Mike Wiacek) */
int my_rename(char *source, char *dest) {
int rename_result = 0;
/* make sure we have something */
if(source == NULL || dest == NULL)
return -1;
/* first see if we can rename file with standard function */
rename_result = rename(source, dest);
/* handle any errors... */
if(rename_result == -1) {
/* an error occurred because the source and dest files are on different filesystems */
if(errno == EXDEV) {
/* try copying the file */
if(my_fcopy(source, dest) == ERROR) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to rename file '%s' to '%s': %s\n", source, dest, strerror(errno));
return -1;
}
/* delete the original file */
unlink(source);
/* reset result since we successfully copied file */
rename_result = 0;
}
/* some other error occurred */
else {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to rename file '%s' to '%s': %s\n", source, dest, strerror(errno));
return rename_result;
}
}
return rename_result;
}
/*
* copy a file from the path at source to the already opened
* destination file dest.
* This is handy when creating tempfiles with mkstemp()
*/
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;
struct stat st;
char *buf;
/* open source file for reading */
if((source_fd = open(source, O_RDONLY, 0644)) < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to open file '%s' for reading: %s\n", source, strerror(errno));
return ERROR;
}
/*
* find out how large the source-file is so we can be sure
* we've written all of it
*/
if(fstat(source_fd, &st) < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to stat source file '%s' for my_fcopy(): %s\n", source, strerror(errno));
close(source_fd);
return ERROR;
}
/*
* If the file is huge, read it and write it in chunks.
* This value (128K) is the result of "pick-one-at-random"
* with some minimal testing and may not be optimal for all
* hardware setups, but it should work ok for most. It's
* faster than 1K buffers and 1M buffers, so change at your
* own peril. Note that it's useful to make it fit in the L2
* cache, so larger isn't necessarily better.
*/
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));
close(source_fd);
return ERROR;
}
/* most of the times, this loop will be gone through once */
while(tot_written < st.st_size) {
int loop_wr = 0;
rd_result = read(source_fd, buf, buf_size);
if(rd_result < 0) {
if(errno == EAGAIN || errno == EINTR)
continue;
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: my_fcopy() failed to read from '%s': %s\n", source, strerror(errno));
break;
}
tot_read += rd_result;
while(loop_wr < rd_result) {
wr_result = write(dest_fd, buf + loop_wr, rd_result - loop_wr);
if(wr_result < 0) {
if(errno == EAGAIN || errno == EINTR)
continue;
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: my_fcopy() failed to write to '%s': %s\n", dest, strerror(errno));
break;
}
loop_wr += wr_result;
}
if(wr_result < 0)
break;
tot_written += loop_wr;
}
/*
* clean up irregardless of how things went. dest_fd comes from
* our caller, so we mustn't close it.
*/
close(source_fd);
free(buf);
if(rd_result < 0 || wr_result < 0) {
/* don't leave half-written files around */
unlink(dest);
return ERROR;
}
return OK;
}
/* copies a file */
int my_fcopy(char *source, char *dest) {
int dest_fd, result;
/* make sure we have something */
if(source == NULL || dest == NULL)
return ERROR;
/* unlink destination file first (not doing so can cause problems on network file systems like CIFS) */
unlink(dest);
/* open destination file for writing */
if((dest_fd = open(dest, O_WRONLY | O_TRUNC | O_CREAT | O_APPEND, 0644)) < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to open file '%s' for writing: %s\n", dest, strerror(errno));
return ERROR;
}
result = my_fdcopy(source, dest, dest_fd);
close(dest_fd);
return result;
}
/******************************************************************/
/******************** DYNAMIC BUFFER FUNCTIONS ********************/
/******************************************************************/
/* initializes a dynamic buffer */
int dbuf_init(dbuf *db, int chunk_size) {
if(db == NULL)
return ERROR;
db->buf = NULL;
db->used_size = 0L;
db->allocated_size = 0L;
db->chunk_size = chunk_size;
return OK;
}
/* frees a dynamic buffer */
int dbuf_free(dbuf *db) {
if(db == NULL)
return ERROR;
if(db->buf != NULL)
my_free(db->buf);
db->buf = NULL;
db->used_size = 0L;
db->allocated_size = 0L;
return OK;
}
/* dynamically expands a string */
int dbuf_strcat(dbuf *db, char *buf) {
char *newbuf = NULL;
unsigned long buflen = 0L;
unsigned long new_size = 0L;
unsigned long memory_needed = 0L;
if(db == NULL || buf == NULL)
return ERROR;
/* how much memory should we allocate (if any)? */
buflen = strlen(buf);
new_size = db->used_size + buflen + 1;
/* we need more memory */
if(db->allocated_size < new_size) {
memory_needed = ((ceil(new_size / db->chunk_size) + 1) * db->chunk_size);
/* allocate memory to store old and new string */
if((newbuf = (char *)realloc((void *)db->buf, (size_t)memory_needed)) == NULL)
return ERROR;
/* update buffer pointer */
db->buf = newbuf;
/* update allocated size */
db->allocated_size = memory_needed;
/* terminate buffer */
db->buf[db->used_size] = '\x0';
}
/* append the new string */
strcat(db->buf, buf);
/* update size allocated */
db->used_size += buflen;
return OK;
}
/******************************************************************/
/******************** 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 *********************/
/******************************************************************/
/* initialize check statistics data structures */
int init_check_stats(void) {
int x = 0;
int y = 0;
for(x = 0; x < MAX_CHECK_STATS_TYPES; x++) {
check_statistics[x].current_bucket = 0;
for(y = 0; y < CHECK_STATS_BUCKETS; y++)
check_statistics[x].bucket[y] = 0;
check_statistics[x].overflow_bucket = 0;
for(y = 0; y < 3; y++)
check_statistics[x].minute_stats[y] = 0;
check_statistics[x].last_update = (time_t)0L;
}
return OK;
}
/* records stats for a given type of check */
int update_check_stats(int check_type, time_t check_time) {
time_t current_time;
unsigned long minutes = 0L;
int new_current_bucket = 0;
int this_bucket = 0;
int x = 0;
if(check_type < 0 || check_type >= MAX_CHECK_STATS_TYPES)
return ERROR;
time(¤t_time);
if((unsigned long)check_time == 0L) {
#ifdef DEBUG_CHECK_STATS
printf("TYPE[%d] CHECK TIME==0!\n", check_type);
#endif
check_time = current_time;
}
/* do some sanity checks on the age of the stats data before we start... */
/* get the new current bucket number */
minutes = ((unsigned long)check_time - (unsigned long)program_start) / 60;
new_current_bucket = minutes % CHECK_STATS_BUCKETS;
/* its been more than 15 minutes since stats were updated, so clear the stats */
if((((unsigned long)current_time - (unsigned long)check_statistics[check_type].last_update) / 60) > CHECK_STATS_BUCKETS) {
for(x = 0; x < CHECK_STATS_BUCKETS; x++)
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);
#endif
}
/* different current bucket number than last time */
else if(new_current_bucket != check_statistics[check_type].current_bucket) {
/* clear stats in buckets between last current bucket and new current bucket - stats haven't been updated in a while */
for(x = check_statistics[check_type].current_bucket; x < (CHECK_STATS_BUCKETS * 2); x++) {
this_bucket = (x + CHECK_STATS_BUCKETS + 1) % CHECK_STATS_BUCKETS;
if(this_bucket == new_current_bucket)
break;
#ifdef DEBUG_CHECK_STATS
printf("CLEARING BUCKET %d, (NEW=%d, OLD=%d)\n", this_bucket, new_current_bucket, check_statistics[check_type].current_bucket);
#endif
/* clear old bucket value */
check_statistics[check_type].bucket[this_bucket] = 0;
}
/* update the current bucket number, push old value to overflow bucket */
check_statistics[check_type].overflow_bucket = check_statistics[check_type].bucket[new_current_bucket];
check_statistics[check_type].current_bucket = new_current_bucket;
check_statistics[check_type].bucket[new_current_bucket] = 0;
}
#ifdef DEBUG_CHECK_STATS
else
printf("NO CLEARING NEEDED\n");
#endif
/* increment the value of the current bucket */
check_statistics[check_type].bucket[new_current_bucket]++;
#ifdef DEBUG_CHECK_STATS
printf("TYPE[%d].BUCKET[%d]=%d\n", check_type, new_current_bucket, check_statistics[check_type].bucket[new_current_bucket]);
printf(" ");
for(x = 0; x < CHECK_STATS_BUCKETS; x++)
printf("[%d] ", check_statistics[check_type].bucket[x]);
printf(" (%d)\n", check_statistics[check_type].overflow_bucket);
#endif
/* record last update time */
check_statistics[check_type].last_update = current_time;
return OK;
}
/* generate 1/5/15 minute stats for a given type of check */
int generate_check_stats(void) {
time_t current_time;
int x = 0;
int new_current_bucket = 0;
int this_bucket = 0;
int last_bucket = 0;
int this_bucket_value = 0;
int last_bucket_value = 0;
int bucket_value = 0;
int seconds = 0;
int minutes = 0;
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);
/* do some sanity checks on the age of the stats data before we start... */
/* get the new current bucket number */
minutes = ((unsigned long)current_time - (unsigned long)program_start) / 60;
new_current_bucket = minutes % CHECK_STATS_BUCKETS;
for(check_type = 0; check_type < MAX_CHECK_STATS_TYPES; check_type++) {
/* its been more than 15 minutes since stats were updated, so clear the stats */
if((((unsigned long)current_time - (unsigned long)check_statistics[check_type].last_update) / 60) > CHECK_STATS_BUCKETS) {
for(x = 0; x < CHECK_STATS_BUCKETS; x++)
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);
#endif
}
/* different current bucket number than last time */
else if(new_current_bucket != check_statistics[check_type].current_bucket) {
/* clear stats in buckets between last current bucket and new current bucket - stats haven't been updated in a while */
for(x = check_statistics[check_type].current_bucket; x < (CHECK_STATS_BUCKETS * 2); x++) {
this_bucket = (x + CHECK_STATS_BUCKETS + 1) % CHECK_STATS_BUCKETS;
if(this_bucket == new_current_bucket)
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);
#endif
/* clear old bucket value */
check_statistics[check_type].bucket[this_bucket] = 0;
}
/* update the current bucket number, push old value to overflow bucket */
check_statistics[check_type].overflow_bucket = check_statistics[check_type].bucket[new_current_bucket];
check_statistics[check_type].current_bucket = new_current_bucket;
check_statistics[check_type].bucket[new_current_bucket] = 0;
}
#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);
#endif
/* update last check time */
check_statistics[check_type].last_update = current_time;
}
/* determine weights to use for this/last buckets */
seconds = ((unsigned long)current_time - (unsigned long)program_start) % 60;
this_bucket_weight = (seconds / 60.0);
last_bucket_weight = ((60 - seconds) / 60.0);
/* update statistics for all check types */
for(check_type = 0; check_type < MAX_CHECK_STATS_TYPES; check_type++) {
/* clear the old statistics */
for(x = 0; x < 3; x++)
check_statistics[check_type].minute_stats[x] = 0;
/* loop through each bucket */
for(x = 0; x < CHECK_STATS_BUCKETS; x++) {
/* which buckets should we use for this/last bucket? */
this_bucket = (check_statistics[check_type].current_bucket + CHECK_STATS_BUCKETS - x) % CHECK_STATS_BUCKETS;
last_bucket = (this_bucket + CHECK_STATS_BUCKETS - 1) % CHECK_STATS_BUCKETS;
/* raw/unweighted value for this bucket */
this_bucket_value = check_statistics[check_type].bucket[this_bucket];
/* raw/unweighted value for last bucket - use overflow bucket if last bucket is current bucket */
if(last_bucket == check_statistics[check_type].current_bucket)
last_bucket_value = check_statistics[check_type].overflow_bucket;
else
last_bucket_value = check_statistics[check_type].bucket[last_bucket];
/* 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));
}
/* 1 minute stats */
if(x == 0)
check_statistics[check_type].minute_stats[0] = bucket_value;
/* 5 minute stats */
if(x < 5)
check_statistics[check_type].minute_stats[1] += bucket_value;
/* 15 minute stats */
if(x < 15)
check_statistics[check_type].minute_stats[2] += bucket_value;
#ifdef DEBUG_CHECK_STATS2
printf("X=%d, THIS[%d]=%d, LAST[%d]=%d, 1/5/15=%d,%d,%d L=%d R=%d\n", x, this_bucket, this_bucket_value, last_bucket, last_bucket_value, check_statistics[check_type].minute_stats[0], check_statistics[check_type].minute_stats[1], check_statistics[check_type].minute_stats[2], left_value, right_value);
#endif
/* record last update time */
check_statistics[check_type].last_update = current_time;
}
#ifdef DEBUG_CHECK_STATS
printf("TYPE[%d] 1/5/15 = %d, %d, %d (seconds=%d, this_weight=%f, last_weight=%f)\n", check_type, check_statistics[check_type].minute_stats[0], check_statistics[check_type].minute_stats[1], check_statistics[check_type].minute_stats[2], seconds, this_bucket_weight, last_bucket_weight);
#endif
}
return OK;
}
/******************************************************************/
/************************ UPDATE FUNCTIONS ************************/
/******************************************************************/
/* check for new releases of Nagios */
int check_for_nagios_updates(int force, int reschedule) {
time_t current_time;
int result = OK;
int api_result = OK;
int do_check = TRUE;
time_t next_check = 0L;
unsigned int rand_seed = 0;
int randnum = 0;
time(¤t_time);
/*
printf("NOW: %s",ctime(¤t_time));
printf("LAST CHECK: %s",ctime(&last_update_check));
*/
/* seed the random generator */
rand_seed = (unsigned int)(current_time + nagios_pid);
srand(rand_seed);
/* generate a (probably) unique ID for this nagios install */
/* the server api currently sees thousands of nagios installs behind single ip addresses, so this help determine if there are really thousands of servers out there, or if some nagios installs are misbehaving */
if(update_uid == 0L)
update_uid = current_time;
/* update chekcs are disabled */
if(check_for_updates == FALSE)
do_check = FALSE;
/* we checked for updates recently, so don't do it again */
if((current_time - last_update_check) < MINIMUM_UPDATE_CHECK_INTERVAL)
do_check = FALSE;
/* the check is being forced */
if(force == TRUE)
do_check = TRUE;
/* do a check */
if(do_check == TRUE) {
/*printf("RUNNING QUERY...\n");*/
/* query api */
api_result = query_update_api();
}
/* should we reschedule the update check? */
if(reschedule == TRUE) {
/*printf("RESCHEDULING...\n");*/
randnum = rand();
/*
printf("RAND: %d\n",randnum);
printf("RANDMAX: %d\n",RAND_MAX);
printf("UCIW: %d\n",UPDATE_CHECK_INTERVAL_WOBBLE);
printf("MULT: %f\n",(float)randnum/RAND_MAX);
*/
/* we didn't do an update, so calculate next possible update time */
if(do_check == FALSE) {
next_check = last_update_check + BASE_UPDATE_CHECK_INTERVAL;
next_check = next_check + (unsigned long)(((float)randnum / RAND_MAX) * UPDATE_CHECK_INTERVAL_WOBBLE);
}
/* we tried to check for an update */
else {
/* api query was okay */
if(api_result == OK) {
next_check = current_time + BASE_UPDATE_CHECK_INTERVAL;
next_check += (unsigned long)(((float)randnum / RAND_MAX) * UPDATE_CHECK_INTERVAL_WOBBLE);
}
/* query resulted in an error - retry at a shorter interval */
else {
next_check = current_time + BASE_UPDATE_CHECK_RETRY_INTERVAL;
next_check += (unsigned long)(((float)randnum / RAND_MAX) * UPDATE_CHECK_RETRY_INTERVAL_WOBBLE);
}
}
/* make sure next check isn't in the past - if it is, schedule a check in 1 minute */
if(next_check < current_time)
next_check = current_time + 60;
/*printf("NEXT CHECK: %s",ctime(&next_check));*/
/* schedule the next update event */
schedule_new_event(EVENT_CHECK_PROGRAM_UPDATE, TRUE, next_check, FALSE, BASE_UPDATE_CHECK_INTERVAL, NULL, TRUE, NULL, NULL, 0);
}
return result;
}
/* checks for updates at api.nagios.org */
int query_update_api(void) {
char *api_server = "api.nagios.org";
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;
int in_header = TRUE;
char *var = NULL;
char *val = NULL;
int sd = 0;
int send_len = 0;
int recv_len = 0;
int update_check_succeeded = FALSE;
/* report a new install, upgrade, or rollback */
/* Nagios monitors the world and we monitor Nagios taking over the world. :-) */
if(last_update_check == (time_t)0L)
report_install = TRUE;
if(last_program_version == NULL || strcmp(PROGRAM_VERSION, last_program_version))
report_install = TRUE;
if(report_install == TRUE) {
asprintf(&api_query_opts, "&firstcheck=1");
if(last_program_version != NULL) {
char *qopts2 = NULL;
asprintf(&qopts2, "%s&last_version=%s", api_query_opts, last_program_version);
my_free(api_query_opts);
api_query_opts = qopts2;
}
}
/* generate the query */
asprintf(&api_query, "v=1&product=nagios&tinycheck=1&stableonly=1&uid=%lu", update_uid);
if(bare_update_check == FALSE) {
char *api_query2 = NULL;
asprintf(&api_query2, "%s&version=%s%s", api_query, PROGRAM_VERSION, (api_query_opts == NULL) ? "" : api_query_opts);
my_free(api_query);
api_query = api_query2;
}
/* generate the HTTP request */
asprintf(&buf,
"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",
api_path, PROGRAM_VERSION, api_server,
strlen(api_query), api_query);
/*
printf("SENDING...\n");
printf("==========\n");
printf("%s",buf);
printf("\n");
*/
result = my_tcp_connect(api_server, 80, &sd, 2);
/*printf("CONN RESULT: %d, SD: %d\n",result,sd);*/
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);*/
/* get response */
recv_len = sizeof(recv_buf);
result = 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);
/* parse the result */
in_header = TRUE;
while((ptr = get_next_string_from_buf(recv_buf, &buf_index, sizeof(recv_buf)))) {
strip(ptr);
current_line++;
if(!strcmp(ptr, "")) {
in_header = FALSE;
continue;
}
if(in_header == TRUE)
continue;
var = strtok(ptr, "=");
val = strtok(NULL, "\n");
/*printf("VAR: %s, VAL: %s\n",var,val);*/
if(!strcmp(var, "UPDATE_AVAILABLE")) {
update_available = atoi(val);
/* we were successful */
update_check_succeeded = TRUE;
}
else if(!strcmp(var, "UPDATE_VERSION")) {
if(new_program_version)
my_free(new_program_version);
new_program_version = strdup(val);
}
else if(!strcmp(var, "UPDATE_RELEASEDATE")) {
}
}
}
/* cleanup */
my_free(buf);
my_free(api_query);
my_free(api_query_opts);
/* we were successful! */
if(update_check_succeeded == TRUE) {
time(&last_update_check);
if(last_program_version)
free(last_program_version);
last_program_version = (char *)strdup(PROGRAM_VERSION);
}
return OK;
}
/******************************************************************/
/************************* MISC FUNCTIONS *************************/
/******************************************************************/
/* returns Nagios version */
char *get_program_version(void) {
return (char *)PROGRAM_VERSION;
}
/* returns Nagios modification date */
char *get_program_modification_date(void) {
return (char *)PROGRAM_MODIFICATION_DATE;
}
/******************************************************************/
/*********************** CLEANUP FUNCTIONS ************************/
/******************************************************************/
/* do some cleanup before we exit */
void cleanup(void) {
#ifdef USE_EVENT_BROKER
/* unload modules */
if(test_scheduling == FALSE && verify_config == FALSE) {
neb_free_callback_list();
neb_unload_all_modules(NEBMODULE_FORCE_UNLOAD, (sigshutdown == TRUE) ? NEBMODULE_NEB_SHUTDOWN : NEBMODULE_NEB_RESTART);
neb_free_module_list();
neb_deinit_modules();
}
#endif
/* free all allocated memory - including macros */
free_memory(get_global_macros());
return;
}
/* free the memory allocated to the linked lists */
void free_memory(nagios_macros *mac) {
timed_event *this_event = NULL;
timed_event *next_event = NULL;
/* free all allocated memory for the object definitions */
free_object_data();
/* 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 memory for global event handlers */
my_free(global_host_event_handler);
my_free(global_service_event_handler);
/* free any notification list that may have been overlooked */
free_notification_list();
/* free obsessive compulsive commands */
my_free(ocsp_command);
my_free(ochp_command);
/*
* free memory associated with macros.
* It's ok to only free the volatile ones, as the non-volatile
* are always free()'d before assignment if they're set.
* Doing a full free of them here means we'll wipe the constant
* macros when we get a reload or restart request through the
* command pipe, or when we receive a SIGHUP.
*/
clear_volatile_macros_r(mac);
free_macrox_names();
/* free illegal char strings */
my_free(illegal_object_chars);
my_free(illegal_output_chars);
/* free nagios user and group */
my_free(nagios_user);
my_free(nagios_group);
/* free version strings */
my_free(last_program_version);
my_free(new_program_version);
/* free file/path variables */
my_free(log_file);
my_free(debug_file);
my_free(temp_file);
my_free(temp_path);
my_free(check_result_path);
my_free(command_file);
my_free(lock_file);
my_free(auth_file);
my_free(p1_file);
my_free(log_archive_path);
return;
}
/* free a notification list that was created */
void free_notification_list(void) {
notification *temp_notification = NULL;
notification *next_notification = NULL;
temp_notification = notification_list;
while(temp_notification != NULL) {
next_notification = temp_notification->next;
my_free(temp_notification);
temp_notification = next_notification;
}
/* reset notification list pointer */
notification_list = NULL;
return;
}
/* reset all system-wide variables, so when we've receive a SIGHUP we can restart cleanly */
int reset_variables(void) {
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);
log_archive_path = (char *)strdup(DEFAULT_LOG_ARCHIVE_PATH);
debug_file = (char *)strdup(DEFAULT_DEBUG_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;
/* reset umask */
umask(S_IWGRP | S_IWOTH);
return OK;
}
nagios/cgi/ 0000775 0000000 0000000 00000000000 12210155146 0013075 5 ustar 00root root 0000000 0000000 nagios/cgi/.gitignore 0000664 0000000 0000000 00000000023 12210155146 0015060 0 ustar 00root root 0000000 0000000 *.o
*.cgi
Makefile
nagios/cgi/Makefile.in 0000664 0000000 0000000 00000014036 12210155146 0015146 0 ustar 00root root 0000000 0000000 ###############################
# Makefile for Nagios CGIs
#
# Last Modified: 10-30-2008
###############################
# Source code directories
SRC_COMMON=../common
SRC_INCLUDE=../include
SRC_XDATA=../xdata
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
CGIDIR=@sbindir@
HTMLDIR=@datarootdir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
COMMAND_OPTS=@COMMAND_OPTS@
STRIP=@STRIP@
CGIEXTRAS=@CGIEXTRAS@
CP=@CP@
CC=@CC@
CFLAGS=-Wall @CFLAGS@ @DEFS@ -DNSCGI
# 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
# Compiler flags for optimization (complements default)
#CFLAGS_WARN=-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs
#CFLAGS_DEBUG=-ggdb3 -g3
#CFLAGS+=$(CFLAGS_WARN) $(CFLAGS_DEBUG)
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@
# Object functions
ODATALIBS=objects-cgi.o xobjects-cgi.o
ODATAHDRS=
ODATADEPS=$(ODATALIBS)
# Host, service, and program status functions
SDATALIBS=statusdata-cgi.o xstatusdata-cgi.o comments-cgi.o downtime-cgi.o
SDATAHDRS=
SDATADEPS=$(SDATALIBS)
# Host and service comment functions
CDATALIBS=
CDATAHDRS=
CDATADEPS=$(CDATALIBS)
# Host and service downtime functions
DDATALIBS=
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)
CGIHDRS=$(SRC_INCLUDE)/config.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/locations.h
CGIDEPS=$(CGILIBS) $(ODATADEPS) $(SDATADEPS)
MATHLIBS=-lm
GDLIBS=@GDLIBS@
all cgis: $(CGIS)
$(CGILIBS): $(CGIHDRS)
######## REQUIRED LIBRARIES ##########
skiplist.o: $(SRC_COMMON)/skiplist.c $(SRC_INCLUDE)/skiplist.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/skiplist.c
macros-cgi.o: $(SRC_COMMON)/macros.c $(SRC_INCLUDE)/macros.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/macros.c
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)
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)
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 $@ $<
########## CGIS ##########
avail.cgi: avail.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ avail.c $(CGILIBS) $(LIBS)
checksanity.cgi: checksanity.c $(CGIDEPS) $(CDATADEPS) $(DDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ checksanity.c $(CGILIBS) $(CDATALIBS) $(DDATALIBS) $(LIBS)
cmd.cgi: cmd.c $(CGIDEPS) $(CDATADEPS) $(DDATADEPS) extcmd_list.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ cmd.c extcmd_list.o $(CGILIBS) $(CDATALIBS) $(DDATALIBS) $(LIBS)
config.cgi: config.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ config.c $(CGILIBS) $(LIBS)
extinfo.cgi: extinfo.c $(CGIDEPS) $(CDATADEPS) $(DDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ extinfo.c $(CGILIBS) $(CDATALIBS) $(DDATALIBS) $(LIBS)
history.cgi: history.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ history.c $(CGILIBS) $(LIBS)
ministatus.cgi: ministatus.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ ministatus.c $(CGILIBS) $(LIBS)
notifications.cgi: notifications.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ notifications.c $(CGILIBS) $(LIBS)
outages.cgi: outages.c $(CGIDEPS) $(CDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ outages.c $(CGILIBS) $(CDATALIBS) $(LIBS)
showlog.cgi: showlog.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ showlog.c $(CGILIBS) $(LIBS)
status.cgi: status.c $(CGIDEPS) $(CDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ status.c $(CGILIBS) $(CDATALIBS) $(LIBS)
statuswml.cgi: statuswml.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ statuswml.c $(CGILIBS) $(LIBS)
statusmap.cgi: statusmap.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ statusmap.c $(CGILIBS) $(GDLIBS) $(LIBS)
statuswrl.cgi: statuswrl.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ statuswrl.c $(CGILIBS) $(MATHLIBS) $(LIBS)
summary.cgi: summary.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ summary.c $(CGILIBS) $(LIBS)
tac.cgi: tac.c $(CGIDEPS) $(CDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ tac.c $(CGILIBS) $(CDATALIBS) $(LIBS)
tac-xml.cgi: tac-xml.c $(CGIDEPS) $(CDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ tac-xml.c $(CGILIBS) $(CDATALIBS) $(LIBS)
trends.cgi: trends.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ trends.c $(CGILIBS) $(GDLIBS) $(LIBS)
histogram.cgi: histogram.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ histogram.c $(CGILIBS) $(GDLIBS) $(LIBS)
clean:
rm -f $(CGIS)
rm -f *.o core gmon.out
rm -f *~ *.*~
distclean: clean
rm -f Makefile cgiutils.h
devclean: distclean
install:
$(MAKE) install-basic
$(MAKE) strip-post-install
install-unstripped:
$(MAKE) install-basic
install-basic:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CGIDIR)
for file in *.cgi; do \
$(INSTALL) -m 775 $(INSTALL_OPTS) $$file $(DESTDIR)$(CGIDIR); \
done
strip-post-install:
for file in *.cgi; do \
$(STRIP) $(DESTDIR)$(CGIDIR)/$$file; \
done
nagios/cgi/avail.c 0000664 0000000 0000000 00000566266 12210155146 0014362 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* AVAIL.C - Nagios Availability CGI
*
* Copyright (c) 2000-2010 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 08-05-2010
*
* 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/comments.h"
#include "../include/statusdata.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
#include "../include/getcgi.h"
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_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
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
/* output types */
#define HTML_OUTPUT 0
#define CSV_OUTPUT 1
/* archived state types */
#define AS_CURRENT_STATE -1 /* special case for initial assumed state */
#define AS_NO_DATA 0
#define AS_PROGRAM_END 1
#define AS_PROGRAM_START 2
#define AS_HOST_UP 3
#define AS_HOST_DOWN 4
#define AS_HOST_UNREACHABLE 5
#define AS_SVC_OK 6
#define AS_SVC_UNKNOWN 7
#define AS_SVC_WARNING 8
#define AS_SVC_CRITICAL 9
#define AS_SVC_DOWNTIME_START 10
#define AS_SVC_DOWNTIME_END 11
#define AS_HOST_DOWNTIME_START 12
#define AS_HOST_DOWNTIME_END 13
#define AS_SOFT_STATE 1
#define AS_HARD_STATE 2
/* display types */
#define DISPLAY_NO_AVAIL 0
#define DISPLAY_HOSTGROUP_AVAIL 1
#define DISPLAY_HOST_AVAIL 2
#define DISPLAY_SERVICE_AVAIL 3
#define DISPLAY_SERVICEGROUP_AVAIL 4
/* subject types */
#define HOST_SUBJECT 0
#define SERVICE_SUBJECT 1
/* standard report times */
#define TIMEPERIOD_CUSTOM 0
#define TIMEPERIOD_TODAY 1
#define TIMEPERIOD_YESTERDAY 2
#define TIMEPERIOD_THISWEEK 3
#define TIMEPERIOD_LASTWEEK 4
#define TIMEPERIOD_THISMONTH 5
#define TIMEPERIOD_LASTMONTH 6
#define TIMEPERIOD_THISQUARTER 7
#define TIMEPERIOD_LASTQUARTER 8
#define TIMEPERIOD_THISYEAR 9
#define TIMEPERIOD_LASTYEAR 10
#define TIMEPERIOD_LAST24HOURS 11
#define TIMEPERIOD_LAST7DAYS 12
#define TIMEPERIOD_LAST31DAYS 13
#define MIN_TIMESTAMP_SPACING 10
#define MAX_ARCHIVE_SPREAD 65
#define MAX_ARCHIVE 65
#define MAX_ARCHIVE_BACKTRACKS 60
authdata current_authdata;
typedef struct archived_state_struct {
time_t time_stamp;
int entry_type;
int state_type;
char *state_info;
int processed_state;
struct archived_state_struct *misc_ptr;
struct archived_state_struct *next;
} archived_state;
typedef struct avail_subject_struct {
int type;
char *host_name;
char *service_description;
archived_state *as_list; /* archived state list */
archived_state *as_list_tail;
archived_state *sd_list; /* scheduled downtime list */
int last_known_state;
time_t earliest_time;
time_t latest_time;
int earliest_state;
int latest_state;
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;
struct avail_subject_struct *next;
} avail_subject;
avail_subject *subject_list = NULL;
time_t t1;
time_t t2;
int display_type = DISPLAY_NO_AVAIL;
int timeperiod_type = TIMEPERIOD_LAST24HOURS;
int show_log_entries = FALSE;
int full_log_entries = FALSE;
int show_scheduled_downtime = TRUE;
int start_second = 0;
int start_minute = 0;
int start_hour = 0;
int start_day = 1;
int start_month = 1;
int start_year = 2000;
int end_second = 0;
int end_minute = 0;
int end_hour = 24;
int end_day = 1;
int end_month = 1;
int end_year = 2000;
int get_date_parts = FALSE;
int select_hostgroups = FALSE;
int select_hosts = FALSE;
int select_servicegroups = FALSE;
int select_services = FALSE;
int select_output_format = FALSE;
int compute_time_from_parts = FALSE;
int show_all_hostgroups = FALSE;
int show_all_hosts = FALSE;
int show_all_servicegroups = FALSE;
int show_all_services = FALSE;
int assume_initial_states = TRUE;
int assume_state_retention = TRUE;
int assume_states_during_notrunning = TRUE;
int initial_assumed_host_state = AS_NO_DATA;
int initial_assumed_service_state = AS_NO_DATA;
int include_soft_states = FALSE;
char *hostgroup_name = "";
char *host_name = "";
char *servicegroup_name = "";
char *svc_description = "";
void create_subject_list(void);
void add_subject(int, char *, char *);
avail_subject *find_subject(int, char *, char *);
void compute_availability(void);
void compute_subject_availability(avail_subject *, time_t);
void compute_subject_availability_times(int, int, time_t, time_t, time_t, avail_subject *, archived_state *);
void compute_subject_downtime(avail_subject *, time_t);
void compute_subject_downtime_times(time_t, time_t, avail_subject *, archived_state *);
void compute_subject_downtime_part_times(time_t, time_t, int, avail_subject *);
void display_hostgroup_availability(void);
void display_specific_hostgroup_availability(hostgroup *);
void display_servicegroup_availability(void);
void display_specific_servicegroup_availability(servicegroup *);
void display_host_availability(void);
void display_service_availability(void);
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 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_scheduled_downtime(int, time_t, avail_subject *);
void free_availability_data(void);
void free_archived_state_list(archived_state *);
void read_archived_state_data(void);
void scan_log_file_for_archived_state_data(char *);
void convert_timeperiod_to_times(int);
unsigned long calculate_total_time(time_t, time_t);
void document_header(int);
void document_footer(void);
int process_cgivars(void);
int backtrack_archives = 2;
int earliest_archive = 0;
int embedded = FALSE;
int display_header = TRUE;
timeperiod *current_timeperiod = NULL;
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];
host *temp_host;
service *temp_service;
int is_authorized = TRUE;
time_t report_start_time;
time_t report_end_time;
int days, hours, minutes, seconds;
hostgroup *temp_hostgroup;
servicegroup *temp_servicegroup;
timeperiod *temp_timeperiod;
time_t t3;
time_t current_time;
struct tm *t;
char *firsthostpointer;
/* 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;
}
/* initialize time period to last 24 hours */
time(¤t_time);
t2 = current_time;
t1 = (time_t)(current_time - (60 * 60 * 24));
/* default number of backtracked archives */
switch(log_rotation_method) {
case LOG_ROTATION_MONTHLY:
backtrack_archives = 1;
break;
case LOG_ROTATION_WEEKLY:
backtrack_archives = 2;
break;
case LOG_ROTATION_DAILY:
backtrack_archives = 4;
break;
case LOG_ROTATION_HOURLY:
backtrack_archives = 8;
break;
default:
backtrack_archives = 2;
break;
}
/* get the arguments passed in the URL */
process_cgivars();
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_authdata);
if(compute_time_from_parts == TRUE)
compute_report_times();
/* make sure times are sane, otherwise swap them */
if(t2 < t1) {
t3 = t2;
t2 = t1;
t1 = t3;
}
/* don't let user create reports in the future */
if(t2 > current_time) {
t2 = current_time;
if(t1 > t2)
t1 = t2 - (60 * 60 * 24);
}
if(display_header == TRUE) {
/* begin top table */
printf("
\n");
}
/* step 3 - ask user for report date range */
if(get_date_parts == TRUE) {
time(¤t_time);
t = localtime(¤t_time);
start_day = 1;
start_year = t->tm_year + 1900;
end_day = t->tm_mday;
end_year = t->tm_year + 1900;
printf("
Step 3: Select Report Options
\n");
printf("
\n");
printf("\n");
printf("
\n");
}
/* step 2 - the user wants to select a hostgroup */
else if(select_hostgroups == TRUE) {
printf("
Step 2: Select Hostgroup
\n");
printf("
\n");
printf("\n");
printf("
\n");
}
/* step 2 - the user wants to select a host */
else if(select_hosts == TRUE) {
printf("
Step 2: Select Host
\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("
Tip: If you want to have the option of getting the availability data in CSV format, select '** ALL HOSTS **' from the pull-down menu.\n");
}
/* step 2 - the user wants to select a servicegroup */
else if(select_servicegroups == TRUE) {
printf("
Step 2: Select Servicegroup
\n");
printf("
\n");
printf("\n");
printf("
\n");
}
/* step 2 - the user wants to select a service */
else if(select_services == TRUE) {
printf("\n");
printf("
Step 2: Select Service
\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("
Tip: If you want to have the option of getting the availability data in CSV format, select '** ALL SERVICES **' from the pull-down menu.\n");
}
/* generate availability report */
else if(display_type != DISPLAY_NO_AVAIL) {
/* check authorization */
is_authorized = TRUE;
if((display_type == DISPLAY_HOST_AVAIL && show_all_hosts == FALSE) || (display_type == DISPLAY_SERVICE_AVAIL && show_all_services == FALSE)) {
if(display_type == DISPLAY_HOST_AVAIL && show_all_hosts == FALSE)
is_authorized = is_authorized_for_host(find_host(host_name), ¤t_authdata);
else
is_authorized = is_authorized_for_service(find_service(host_name, svc_description), ¤t_authdata);
}
if(is_authorized == FALSE)
printf("
It appears as though you are not authorized to view information for the specified %s...
\n", (display_type == DISPLAY_HOST_AVAIL) ? "host" : "service");
else {
time(&report_start_time);
/* create list of subjects to collect availability data for */
create_subject_list();
/* read in all necessary archived state data */
read_archived_state_data();
/* compute availability data */
compute_availability();
time(&report_end_time);
if(output_format == HTML_OUTPUT) {
get_time_breakdown((time_t)(report_end_time - report_start_time), &days, &hours, &minutes, &seconds);
printf("
[ Availability report completed in %d min %d sec ]
\n", minutes, seconds);
printf("
\n");
}
/* display availability data */
if(display_type == DISPLAY_HOST_AVAIL)
display_host_availability();
else if(display_type == DISPLAY_SERVICE_AVAIL)
display_service_availability();
else if(display_type == DISPLAY_HOSTGROUP_AVAIL)
display_hostgroup_availability();
else if(display_type == DISPLAY_SERVICEGROUP_AVAIL)
display_servicegroup_availability();
/* free memory allocated to availability data */
free_availability_data();
}
}
/* step 1 - ask the user what kind of report they want */
else {
printf("
Step 1: Select Report Type
\n");
printf("
\n");
printf("\n");
printf("
\n");
}
document_footer();
/* free all other allocated memory */
free_memory();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
time_t expire_time;
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
time(¤t_time);
get_time_string(¤t_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
printf("Last-Modified: %s\r\n", date_time);
expire_time = (time_t)0;
get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
printf("Expires: %s\r\n", date_time);
if(output_format == HTML_OUTPUT)
printf("Content-type: text/html\r\n\r\n");
else {
printf("Content-type: text/csv\r\n\r\n");
return;
}
if(embedded == TRUE || output_format == CSV_OUTPUT)
return;
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("Nagios Availability\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("\n", url_stylesheets_path, COMMON_CSS);
printf("\n", url_stylesheets_path, AVAIL_CSS);
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(AVAIL_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(output_format != HTML_OUTPUT)
return;
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(AVAIL_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
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) {
x++;
continue;
}
/* we found the hostgroup argument */
else if(!strcmp(variables[x], "hostgroup")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((hostgroup_name = (char *)strdup(variables[x])) == NULL)
hostgroup_name = "";
strip_html_brackets(hostgroup_name);
display_type = DISPLAY_HOSTGROUP_AVAIL;
show_all_hostgroups = (strcmp(hostgroup_name, "all")) ? FALSE : TRUE;
}
/* we found the servicegroup argument */
else if(!strcmp(variables[x], "servicegroup")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((servicegroup_name = (char *)strdup(variables[x])) == NULL)
servicegroup_name = "";
strip_html_brackets(servicegroup_name);
display_type = DISPLAY_SERVICEGROUP_AVAIL;
show_all_servicegroups = (strcmp(servicegroup_name, "all")) ? FALSE : TRUE;
}
/* we found the host argument */
else if(!strcmp(variables[x], "host")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((host_name = (char *)strdup(variables[x])) == NULL)
host_name = "";
strip_html_brackets(host_name);
display_type = DISPLAY_HOST_AVAIL;
show_all_hosts = (strcmp(host_name, "all")) ? FALSE : TRUE;
}
/* we found the service description argument */
else if(!strcmp(variables[x], "service")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((svc_description = (char *)strdup(variables[x])) == NULL)
svc_description = "";
strip_html_brackets(svc_description);
display_type = DISPLAY_SERVICE_AVAIL;
show_all_services = (strcmp(svc_description, "all")) ? FALSE : TRUE;
}
/* we found first time argument */
else if(!strcmp(variables[x], "t1")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
t1 = (time_t)strtoul(variables[x], NULL, 10);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = FALSE;
}
/* we found first time argument */
else if(!strcmp(variables[x], "t2")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
t2 = (time_t)strtoul(variables[x], NULL, 10);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = FALSE;
}
/* we found the assume initial states option */
else if(!strcmp(variables[x], "assumeinitialstates")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "yes"))
assume_initial_states = TRUE;
else
assume_initial_states = FALSE;
}
/* we found the assume state during program not running option */
else if(!strcmp(variables[x], "assumestatesduringnotrunning")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "yes"))
assume_states_during_notrunning = TRUE;
else
assume_states_during_notrunning = FALSE;
}
/* we found the initial assumed host state option */
else if(!strcmp(variables[x], "initialassumedhoststate")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
initial_assumed_host_state = atoi(variables[x]);
}
/* we found the initial assumed service state option */
else if(!strcmp(variables[x], "initialassumedservicestate")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
initial_assumed_service_state = atoi(variables[x]);
}
/* we found the assume state retention option */
else if(!strcmp(variables[x], "assumestateretention")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "yes"))
assume_state_retention = TRUE;
else
assume_state_retention = FALSE;
}
/* we found the include soft states option */
else if(!strcmp(variables[x], "includesoftstates")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "yes"))
include_soft_states = TRUE;
else
include_soft_states = FALSE;
}
/* we found the backtrack archives argument */
else if(!strcmp(variables[x], "backtrack")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
backtrack_archives = atoi(variables[x]);
if(backtrack_archives < 0)
backtrack_archives = 0;
if(backtrack_archives > MAX_ARCHIVE_BACKTRACKS)
backtrack_archives = MAX_ARCHIVE_BACKTRACKS;
#ifdef DEBUG
printf("BACKTRACK ARCHIVES: %d\n", backtrack_archives);
#endif
}
/* we found the standard timeperiod argument */
else if(!strcmp(variables[x], "timeperiod")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "today"))
timeperiod_type = TIMEPERIOD_TODAY;
else if(!strcmp(variables[x], "yesterday"))
timeperiod_type = TIMEPERIOD_YESTERDAY;
else if(!strcmp(variables[x], "thisweek"))
timeperiod_type = TIMEPERIOD_THISWEEK;
else if(!strcmp(variables[x], "lastweek"))
timeperiod_type = TIMEPERIOD_LASTWEEK;
else if(!strcmp(variables[x], "thismonth"))
timeperiod_type = TIMEPERIOD_THISMONTH;
else if(!strcmp(variables[x], "lastmonth"))
timeperiod_type = TIMEPERIOD_LASTMONTH;
else if(!strcmp(variables[x], "thisquarter"))
timeperiod_type = TIMEPERIOD_THISQUARTER;
else if(!strcmp(variables[x], "lastquarter"))
timeperiod_type = TIMEPERIOD_LASTQUARTER;
else if(!strcmp(variables[x], "thisyear"))
timeperiod_type = TIMEPERIOD_THISYEAR;
else if(!strcmp(variables[x], "lastyear"))
timeperiod_type = TIMEPERIOD_LASTYEAR;
else if(!strcmp(variables[x], "last24hours"))
timeperiod_type = TIMEPERIOD_LAST24HOURS;
else if(!strcmp(variables[x], "last7days"))
timeperiod_type = TIMEPERIOD_LAST7DAYS;
else if(!strcmp(variables[x], "last31days"))
timeperiod_type = TIMEPERIOD_LAST31DAYS;
else if(!strcmp(variables[x], "custom"))
timeperiod_type = TIMEPERIOD_CUSTOM;
else
continue;
convert_timeperiod_to_times(timeperiod_type);
compute_time_from_parts = FALSE;
}
/* we found the embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
/* we found the noheader option */
else if(!strcmp(variables[x], "noheader"))
display_header = FALSE;
/* we found the CSV output option */
else if(!strcmp(variables[x], "csvoutput")) {
display_header = FALSE;
output_format = CSV_OUTPUT;
}
/* we found the log entries option */
else if(!strcmp(variables[x], "show_log_entries"))
show_log_entries = TRUE;
/* we found the full log entries option */
else if(!strcmp(variables[x], "full_log_entries"))
full_log_entries = TRUE;
/* we found the get date parts option */
else if(!strcmp(variables[x], "get_date_parts"))
get_date_parts = TRUE;
/* we found the report type selection option */
else if(!strcmp(variables[x], "report_type")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "hostgroups"))
select_hostgroups = TRUE;
else if(!strcmp(variables[x], "servicegroups"))
select_servicegroups = TRUE;
else if(!strcmp(variables[x], "hosts"))
select_hosts = TRUE;
else
select_services = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "smon")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_month = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "sday")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_day = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "syear")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_year = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "smin")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_minute = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "ssec")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_second = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "shour")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_hour = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "emon")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_month = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "eday")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_day = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "eyear")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_year = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "emin")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_minute = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "esec")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_second = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "ehour")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_hour = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found the show scheduled downtime option */
else if(!strcmp(variables[x], "showscheduleddowntime")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "yes"))
show_scheduled_downtime = TRUE;
else
show_scheduled_downtime = FALSE;
}
/* we found the report timeperiod option */
else if(!strcmp(variables[x], "rpttimeperiod")) {
timeperiod *temp_timeperiod;
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
for(temp_timeperiod = timeperiod_list; temp_timeperiod != NULL; temp_timeperiod = temp_timeperiod->next) {
if(!strcmp(url_encode(temp_timeperiod->name), variables[x])) {
current_timeperiod = temp_timeperiod;
break;
}
}
}
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
/* computes availability data for all subjects */
void compute_availability(void) {
avail_subject *temp_subject;
time_t current_time;
time(¤t_time);
for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
compute_subject_availability(temp_subject, current_time);
compute_subject_downtime(temp_subject, current_time);
}
return;
}
/* computes availability data for a given subject */
void compute_subject_availability(avail_subject *subject, time_t current_time) {
archived_state *temp_as;
archived_state *last_as;
time_t a;
time_t b;
int current_state = AS_NO_DATA;
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;
/* if left hand of graph is after current time, we can't do anything at all.... */
if(t1 > current_time)
return;
/* get current state of host or service if possible */
if(subject->type == HOST_SUBJECT)
hststatus = find_hoststatus(subject->host_name);
else
svcstatus = find_servicestatus(subject->host_name, subject->service_description);
/************************************/
/* INSERT CURRENT STATE (IF WE CAN) */
/************************************/
/* if current time DOES NOT fall within graph bounds, so we can't do anything as far as assuming current state */
/* if we don't have any data, assume current state (if possible) */
if(subject->as_list == NULL && current_time > t1 && current_time <= t2) {
/* 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(subject->type == HOST_SUBJECT) {
if(hststatus != NULL) {
if(hststatus->status == HOST_DOWN)
subject->last_known_state = AS_HOST_DOWN;
else if(hststatus->status == HOST_UNREACHABLE)
subject->last_known_state = AS_HOST_UNREACHABLE;
else if(hststatus->status == HOST_UP)
subject->last_known_state = AS_HOST_UP;
else
subject->last_known_state = AS_NO_DATA;
if(subject->last_known_state != AS_NO_DATA) {
/* 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;
}
}
}
else {
if(svcstatus != NULL) {
if(svcstatus->status == SERVICE_OK)
subject->last_known_state = AS_SVC_OK;
else if(svcstatus->status == SERVICE_WARNING)
subject->last_known_state = AS_SVC_WARNING;
else if(svcstatus->status == SERVICE_CRITICAL)
subject->last_known_state = AS_SVC_CRITICAL;
else if(svcstatus->status == SERVICE_UNKNOWN)
subject->last_known_state = AS_SVC_UNKNOWN;
else
subject->last_known_state = AS_NO_DATA;
if(subject->last_known_state != AS_NO_DATA) {
/* 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;
}
}
}
}
/******************************************/
/* INSERT FIRST ASSUMED STATE (IF WE CAN) */
/******************************************/
if((subject->type == HOST_SUBJECT && initial_assumed_host_state != AS_NO_DATA) || (subject->type == SERVICE_SUBJECT && initial_assumed_service_state != AS_NO_DATA)) {
/* see if its okay to assume initial state for this subject */
error = FALSE;
if(subject->type == SERVICE_SUBJECT) {
if(initial_assumed_service_state != AS_SVC_OK && initial_assumed_service_state != AS_SVC_WARNING && initial_assumed_service_state != AS_SVC_UNKNOWN && initial_assumed_service_state != AS_SVC_CRITICAL && initial_assumed_service_state != AS_CURRENT_STATE)
error = TRUE;
else
initial_assumed_state = initial_assumed_service_state;
if(initial_assumed_service_state == AS_CURRENT_STATE && svcstatus == NULL)
error = TRUE;
}
else {
if(initial_assumed_host_state != AS_HOST_UP && initial_assumed_host_state != AS_HOST_DOWN && initial_assumed_host_state != AS_HOST_UNREACHABLE && initial_assumed_host_state != AS_CURRENT_STATE)
error = TRUE;
else
initial_assumed_state = initial_assumed_host_state;
if(initial_assumed_host_state == AS_CURRENT_STATE && hststatus == NULL)
error = TRUE;
}
/* get the current state if applicable */
if(((subject->type == HOST_SUBJECT && initial_assumed_host_state == AS_CURRENT_STATE) || (subject->type == SERVICE_SUBJECT && initial_assumed_service_state == AS_CURRENT_STATE)) && error == FALSE) {
if(subject->type == SERVICE_SUBJECT) {
switch(svcstatus->status) {
case SERVICE_OK:
initial_assumed_state = AS_SVC_OK;
break;
case SERVICE_WARNING:
initial_assumed_state = AS_SVC_WARNING;
break;
case SERVICE_UNKNOWN:
initial_assumed_state = AS_SVC_UNKNOWN;
break;
case SERVICE_CRITICAL:
initial_assumed_state = AS_SVC_CRITICAL;
break;
default:
error = TRUE;
break;
}
}
else {
switch(hststatus->status) {
case HOST_DOWN:
initial_assumed_state = AS_HOST_DOWN;
break;
case HOST_UNREACHABLE:
initial_assumed_state = AS_HOST_UNREACHABLE;
break;
case HOST_UP:
initial_assumed_state = AS_HOST_UP;
break;
default:
error = TRUE;
break;
}
}
}
if(error == FALSE) {
/* add this assumed state entry before any entries in the list and <= t1 */
if(subject->as_list == NULL)
initial_assumed_time = t1;
else if(subject->as_list->time_stamp > t1)
initial_assumed_time = t1;
else
initial_assumed_time = subject->as_list->time_stamp - 1;
if(subject->type == HOST_SUBJECT)
add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Host State Assumed (Faked Log Entry)", subject);
else
add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Service State Assumed (Faked Log Entry)", subject);
}
}
/**************************************/
/* BAIL OUT IF WE DON'T HAVE ANYTHING */
/**************************************/
have_some_real_data = FALSE;
for(temp_as = subject->as_list; temp_as != NULL; temp_as = temp_as->next) {
if(temp_as->entry_type != AS_NO_DATA && temp_as->entry_type != AS_PROGRAM_START && temp_as->entry_type != AS_PROGRAM_END) {
have_some_real_data = TRUE;
break;
}
}
if(have_some_real_data == FALSE)
return;
last_as = NULL;
subject->earliest_time = t2;
subject->latest_time = t1;
#ifdef DEBUG
printf("--- BEGINNING/MIDDLE SECTION --- \n");
#endif
/**********************************/
/* BEGINNING/MIDDLE SECTION */
/**********************************/
for(temp_as = subject->as_list; temp_as != NULL; temp_as = temp_as->next) {
/* keep this as last known state if this is the first entry or if it occurs before the starting point of the graph */
if((temp_as->time_stamp <= t1 || temp_as == subject->as_list) && (temp_as->entry_type != AS_NO_DATA && temp_as->entry_type != AS_PROGRAM_END && temp_as->entry_type != AS_PROGRAM_START)) {
subject->last_known_state = temp_as->entry_type;
#ifdef DEBUG
printf("SETTING LAST KNOWN STATE=%d \n", subject->last_known_state);
#endif
}
/* skip this entry if it occurs before the starting point of the graph */
if(temp_as->time_stamp <= t1) {
#ifdef DEBUG
printf("SKIPPING PRE-EVENT: %d @ %lu \n", temp_as->entry_type, temp_as->time_stamp);
#endif
last_as = temp_as;
continue;
}
/* graph this span if we're not on the first item */
if(last_as != NULL) {
a = last_as->time_stamp;
b = temp_as->time_stamp;
/* we've already passed the last time displayed in the graph */
if(a > t2)
break;
/* only graph this data if its on the graph */
else if(b > t1) {
/* clip last time if it exceeds graph limits */
if(b > t2)
b = t2;
/* clip first time if it precedes graph limits */
if(a < t1)
a = t1;
/* save this time if its the earliest we've graphed */
if(a < subject->earliest_time) {
subject->earliest_time = a;
subject->earliest_state = last_as->entry_type;
}
/* save this time if its the latest we've graphed */
if(b > subject->latest_time) {
subject->latest_time = b;
subject->latest_state = last_as->entry_type;
}
/* compute availability times for this chunk */
compute_subject_availability_times(last_as->entry_type, temp_as->entry_type, last_as->time_stamp, a, b, subject, temp_as);
/* return if we've reached the end of the graph limits */
if(b >= t2) {
last_as = temp_as;
break;
}
}
}
/* keep track of the last item */
last_as = temp_as;
}
#ifdef DEBUG
printf("--- END SECTION --- \n");
#endif
/**********************************/
/* END SECTION */
/**********************************/
if(last_as != NULL) {
/* don't process an entry that is beyond the limits of the graph */
if(last_as->time_stamp < t2) {
time(¤t_time);
b = current_time;
if(b > t2)
b = t2;
a = last_as->time_stamp;
if(a < t1)
a = t1;
/* fake the current state (it doesn't really matter for graphing) */
if(subject->type == HOST_SUBJECT)
current_state = AS_HOST_UP;
else
current_state = AS_SVC_OK;
/* compute availability times for last state */
compute_subject_availability_times(last_as->entry_type, current_state, last_as->time_stamp, a, b, subject, last_as);
}
}
return;
}
/* 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;
int weekday;
timerange *temp_timerange;
unsigned long temp_duration;
unsigned long temp_end;
unsigned long temp_start;
unsigned long start;
unsigned long end;
#ifdef DEBUG
if(subject->type == HOST_SUBJECT)
printf("HOST '%s'...\n", subject->host_name);
else
printf("SERVICE '%s' ON HOST '%s'...\n", subject->service_description, subject->host_name);
printf("COMPUTING %d->%d FROM %lu to %lu (%lu seconds) FOR %s \n", first_state, last_state, start_time, end_time, (end_time - start_time), (subject->type == HOST_SUBJECT) ? "HOST" : "SERVICE");
#endif
/* clip times if necessary */
if(start_time < t1)
start_time = t1;
if(end_time > t2)
end_time = t2;
/* make sure this is a valid time */
if(start_time > t2)
return;
if(end_time < t1)
return;
/* MickeM - attempt to handle the current time_period (if any) */
if(current_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_today = (unsigned long)mktime(t);
weekday = t->tm_wday;
while(midnight_today < end_time) {
temp_duration = 0;
temp_end = min(86400, end_time - midnight_today);
temp_start = 0;
if(start_time > midnight_today)
temp_start = start_time - midnight_today;
#ifdef DEBUG
printf("Matching: %ld -> %ld. (%ld -> %ld) \n", temp_start, temp_end, midnight_today + temp_start, midnight_today + temp_end);
#endif
/* check all time ranges for this day of the week */
for(temp_timerange = current_timeperiod->days[weekday]; temp_timerange != NULL; temp_timerange = temp_timerange->next) {
#ifdef DEBUG
printf("
\n");
}
/* get archive to use */
get_log_archive_to_use(archive, archive_file, sizeof(archive_file) - 1);
/* cut the pathname for security, and the remaining slash for clarity */
archive_basename = (char *)&archive_file;
if(strrchr((char *)&archive_basename, '/') != NULL)
archive_basename = strrchr((char *)&archive_file, '/') + 1;
/* now it's safe to print the filename */
printf("
File: %s
\n", archive_basename);
return;
}
/* prints the additional notes or action url for a hostgroup (with macros substituted) */
void print_extra_hostgroup_url(char *group_name, char *url) {
char input_buffer[MAX_INPUT_BUFFER] = "";
char output_buffer[MAX_INPUT_BUFFER] = "";
char *temp_buffer;
int in_macro = FALSE;
hostgroup *temp_hostgroup = NULL;
if(group_name == NULL || url == NULL)
return;
temp_hostgroup = find_hostgroup(group_name);
if(temp_hostgroup == NULL) {
printf("%s", url);
return;
}
strncpy(input_buffer, url, sizeof(input_buffer) - 1);
input_buffer[sizeof(input_buffer) - 1] = '\x0';
for(temp_buffer = my_strtok(input_buffer, "$"); temp_buffer != NULL; temp_buffer = my_strtok(NULL, "$")) {
if(in_macro == FALSE) {
if(strlen(output_buffer) + strlen(temp_buffer) < sizeof(output_buffer) - 1) {
strncat(output_buffer, temp_buffer, sizeof(output_buffer) - strlen(output_buffer) - 1);
output_buffer[sizeof(output_buffer) - 1] = '\x0';
}
in_macro = TRUE;
}
else {
if(strlen(output_buffer) + strlen(temp_buffer) < sizeof(output_buffer) - 1) {
if(!strcmp(temp_buffer, "HOSTGROUPNAME"))
strncat(output_buffer, url_encode(temp_hostgroup->group_name), sizeof(output_buffer) - strlen(output_buffer) - 1);
}
in_macro = FALSE;
}
}
printf("%s", output_buffer);
return;
}
/* prints the additional notes or action url for a servicegroup (with macros substituted) */
void print_extra_servicegroup_url(char *group_name, char *url) {
char input_buffer[MAX_INPUT_BUFFER] = "";
char output_buffer[MAX_INPUT_BUFFER] = "";
char *temp_buffer;
int in_macro = FALSE;
servicegroup *temp_servicegroup = NULL;
if(group_name == NULL || url == NULL)
return;
temp_servicegroup = find_servicegroup(group_name);
if(temp_servicegroup == NULL) {
printf("%s", url);
return;
}
strncpy(input_buffer, url, sizeof(input_buffer) - 1);
input_buffer[sizeof(input_buffer) - 1] = '\x0';
for(temp_buffer = my_strtok(input_buffer, "$"); temp_buffer != NULL; temp_buffer = my_strtok(NULL, "$")) {
if(in_macro == FALSE) {
if(strlen(output_buffer) + strlen(temp_buffer) < sizeof(output_buffer) - 1) {
strncat(output_buffer, temp_buffer, sizeof(output_buffer) - strlen(output_buffer) - 1);
output_buffer[sizeof(output_buffer) - 1] = '\x0';
}
in_macro = TRUE;
}
else {
if(strlen(output_buffer) + strlen(temp_buffer) < sizeof(output_buffer) - 1) {
if(!strcmp(temp_buffer, "SERVICEGROUPNAME"))
strncat(output_buffer, url_encode(temp_servicegroup->group_name), sizeof(output_buffer) - strlen(output_buffer) - 1);
}
in_macro = FALSE;
}
}
printf("%s", output_buffer);
return;
}
/* include user-defined SSI footers or headers */
void include_ssi_files(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");
common_ssi_file[sizeof(common_ssi_file) - 1] = '\x0';
/* CGI-specific header or footer */
strncpy(raw_cgi_name, cgi_name, sizeof(raw_cgi_name) - 1);
raw_cgi_name[sizeof(raw_cgi_name) - 1] = '\x0';
stripped_cgi_name = strtok(raw_cgi_name, ".");
snprintf(cgi_ssi_file, sizeof(cgi_ssi_file) - 1, "%s%s-%s.ssi", physical_ssi_path, (stripped_cgi_name == NULL) ? "" : stripped_cgi_name, (type == SSI_HEADER) ? "header" : "footer");
cgi_ssi_file[sizeof(cgi_ssi_file) - 1] = '\x0';
if(type == SSI_HEADER) {
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");
}
return;
}
/* include user-defined SSI footer or header */
void include_ssi_file(char *filename) {
char buffer[MAX_INPUT_BUFFER];
FILE *fp;
struct stat stat_result;
int call_return;
/* if file is executable, we want to run it rather than print it */
call_return = stat(filename, &stat_result);
/* file is executable */
if(call_return == 0 && (stat_result.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
/* must flush output stream first so that output
from script shows up in correct place. Other choice
is to open program under pipe and copy the data from
the program to our output stream.
*/
fflush(stdout);
/* ignore return status from system call. */
call_return = system(filename);
return;
}
/* an error occurred trying to stat() the file */
else if(call_return != 0) {
/* Handle error conditions. Assume that standard posix error codes and errno are available. If not, comment this section out. */
switch(errno) {
case ENOTDIR: /* - A component of the path is not a directory. */
case ELOOP: /* Too many symbolic links encountered while traversing the path. */
case EFAULT: /* Bad address. */
case ENOMEM: /* Out of memory (i.e. kernel memory). */
case ENAMETOOLONG: /* File name too long. */
printf(" A stat call returned %d while looking for the file %s. ", errno, filename);
return;
case EACCES: /* Permission denied. -- The file should be accessible by nagios. */
printf(" A stat call returned a permissions error(%d) while looking for the file %s. ", errno, filename);
return;
case ENOENT: /* A component of the path file_name does not exist, or the path is an empty string. Just return if the file doesn't exist. */
return;
default:
return;
}
}
fp = fopen(filename, "r");
if(fp == NULL)
return;
/* print all lines in the SSI file */
while(fgets(buffer, (int)(sizeof(buffer) - 1), fp) != NULL)
printf("%s", buffer);
fclose(fp);
return;
}
/* displays an error if CGI config file could not be read */
void cgi_config_file_error(char *config_file) {
printf("
Whoops!
\n");
printf("
Error: Could not open CGI config file '%s' for reading!
\n", config_file);
printf("
\n");
printf("Here are some things you should check in order to resolve this error:\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Make sure you've installed a CGI config file in its proper location. See the error message about for details on where the CGI is expecting to find the configuration file. A sample CGI configuration file (named cgi.cfg) can be found in the sample-config/ subdirectory of the Nagios source code distribution.\n");
printf("
Make sure the user your web server is running as has permission to read the CGI config file.\n");
printf("
\n");
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("
\n");
return;
}
/* displays an error if main config file could not be read */
void main_config_file_error(char *config_file) {
printf("
Whoops!
\n");
printf("
Error: Could not open main config file '%s' for reading!
\n", config_file);
printf("
\n");
printf("Here are some things you should check in order to resolve this error:\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Make sure you've installed a main config file in its proper location. See the error message about for details on where the CGI is expecting to find the configuration file. A sample main configuration file (named nagios.cfg) can be found in the sample-config/ subdirectory of the Nagios source code distribution.\n");
printf("
Make sure the user your web server is running as has permission to read the main config file.\n");
printf("
\n");
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("
\n");
return;
}
/* displays an error if object data could not be read */
void object_data_error(void) {
printf("
Whoops!
\n");
printf("
Error: Could not read object configuration data!
\n");
printf("
\n");
printf("Here are some things you should check in order to resolve this error:\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Verify configuration options using the -v command-line option to check for errors.\n");
printf("
Check the Nagios log file for messages relating to startup or status data errors.\n");
printf("
\n");
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("
\n");
return;
}
/* displays an error if status data could not be read */
void status_data_error(void) {
printf("
Whoops!
\n");
printf("
Error: Could not read host and service status information!
\n");
printf("
\n");
printf("The most common cause of this error message (especially for new users), is the fact that Nagios is not actually running. If Nagios is indeed not running, this is a normal error message. It simply indicates that the CGIs could not obtain the current status of hosts and services that are being monitored. If you've just installed things, make sure you read the documentation on starting Nagios.\n");
printf("
\n");
printf("
\n");
printf("Some other things you should check in order to resolve this error include:\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Check the Nagios log file for messages relating to startup or status data errors.\n");
printf("
Always verify configuration options using the -v command-line option before starting or restarting Nagios!\n");
printf("
\n");
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("
\n");
return;
}
/* displays context-sensitive help window */
void display_context_help(char *chid) {
char *icon = CONTEXT_HELP_ICON1;
if(show_context_help == FALSE)
return;
/* change icon if necessary */
if(!strcmp(chid, CONTEXTHELP_TAC))
icon = CONTEXT_HELP_ICON2;
printf("\n", url_context_help_path, chid, url_context_help_path, chid, url_images_path, icon);
return;
}
void display_splunk_host_url(host *hst) {
if(enable_splunk_integration == FALSE)
return;
if(hst == NULL)
return;
printf("\n", splunk_url, url_encode(hst->name), url_images_path, SPLUNK_SMALL_WHITE_ICON);
return;
}
void display_splunk_service_url(service *svc) {
if(enable_splunk_integration == FALSE)
return;
if(svc == NULL)
return;
printf("\n", url_encode(svc->description), url_images_path, SPLUNK_SMALL_WHITE_ICON);
return;
}
void display_splunk_generic_url(char *buf, int icon) {
char *newbuf = NULL;
if(enable_splunk_integration == FALSE)
return;
if(buf == NULL)
return;
if((newbuf = (char *)strdup(buf)) == NULL)
return;
strip_splunk_query_terms(newbuf);
printf("", splunk_url, url_encode(newbuf));
if(icon > 0)
printf("", url_images_path, (icon == 1) ? SPLUNK_SMALL_WHITE_ICON : SPLUNK_SMALL_BLACK_ICON);
printf("\n");
free(newbuf);
return;
}
/* strip quotes and from string */
void strip_splunk_query_terms(char *buffer) {
register int x;
register int y;
register int z;
if(buffer == NULL || buffer[0] == '\x0')
return;
/* remove all occurances 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] == '=')
buffer[y++] = ' ';
else
buffer[y++] = buffer[x];
}
buffer[y++] = '\x0';
return;
}
nagios/cgi/cmd.c 0000664 0000000 0000000 00000335675 12210155146 0014027 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* CMD.C - Nagios Command CGI
*
* Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 08-28-2010
*
* 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/comments.h"
#include "../include/downtime.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
#include "../include/getcgi.h"
extern const char *extcmd_get_name(int id);
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;
#define MAX_AUTHOR_LENGTH 64
#define MAX_COMMENT_LENGTH 1024
#define HTML_CONTENT 0
#define WML_CONTENT 1
char *host_name = "";
char *hostgroup_name = "";
char *servicegroup_name = "";
char *service_desc = "";
char *comment_author = "";
char *comment_data = "";
char *start_time_string = "";
char *end_time_string = "";
unsigned long comment_id = 0;
unsigned long downtime_id = 0;
int notification_delay = 0;
int schedule_delay = 0;
int persistent_comment = FALSE;
int sticky_ack = FALSE;
int send_notification = FALSE;
int force_check = FALSE;
int plugin_state = STATE_OK;
char plugin_output[MAX_INPUT_BUFFER] = "";
char performance_data[MAX_INPUT_BUFFER] = "";
time_t start_time = 0L;
time_t end_time = 0L;
int affect_host_and_services = FALSE;
int propagate_to_children = FALSE;
int fixed = FALSE;
unsigned long duration = 0L;
unsigned long triggered_by = 0L;
int child_options = 0;
int force_notification = 0;
int broadcast_notification = 0;
int command_type = CMD_NONE;
int command_mode = CMDMODE_REQUEST;
int content_type = HTML_CONTENT;
int display_header = TRUE;
authdata current_authdata;
void show_command_help(int);
void request_command_data(int);
void commit_command_data(int);
int commit_command(int);
int write_command_to_file(char *);
void clean_comment_data(char *);
void document_header(int);
void document_footer(void);
int process_cgivars(void);
int string_to_time(char *, time_t *);
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);
if(content_type == WML_CONTENT)
printf("
Error: Could not open CGI config file!
\n");
else
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);
if(content_type == WML_CONTENT)
printf("
Error: Could not open main config file!
\n");
else
main_config_file_error(main_config_file);
document_footer();
return ERROR;
}
/* This requires the date_format parameter in the main config file */
if(strcmp(start_time_string, ""))
string_to_time(start_time_string, &start_time);
if(strcmp(end_time_string, ""))
string_to_time(end_time_string, &end_time);
/* read all object configuration data */
result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA);
if(result == ERROR) {
document_header(FALSE);
if(content_type == WML_CONTENT)
printf("
Error: Could not read object config data!
\n");
else
object_data_error();
document_footer();
return ERROR;
}
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_authdata);
if(display_header == TRUE) {
/* begin top table */
printf("
\n");
}
/* authorized_for_read_only should take priority */
if(is_authorized_for_read_only(¤t_authdata) == TRUE) {
printf("
It appears as though you do not have permission to submit the command 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");
document_footer();
/* free allocated memory */
free_memory();
free_object_data();
return OK;
}
/* if no command was specified... */
if(command_type == CMD_NONE) {
if(content_type == WML_CONTENT)
printf("
Error: No command specified!
\n");
else
printf("
Error: No command was specified
\n");
}
/* if this is the first request for a command, present option */
else if(command_mode == CMDMODE_REQUEST)
request_command_data(command_type);
/* the user wants to commit the command */
else if(command_mode == CMDMODE_COMMIT)
commit_command_data(command_type);
document_footer();
/* free allocated memory */
free_memory();
free_object_data();
return OK;
}
void document_header(int use_stylesheet) {
if(content_type == WML_CONTENT) {
printf("Content-type: text/vnd.wap.wml\r\n\r\n");
printf("\n");
printf("\n");
printf("\n");
printf("\n");
}
else {
printf("Content-type: text/html\r\n\r\n");
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("External Command Interface\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("\n", url_stylesheets_path, COMMON_CSS);
printf("\n", url_stylesheets_path, COMMAND_CSS);
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(COMMAND_CGI, SSI_HEADER);
}
return;
}
void document_footer(void) {
if(content_type == WML_CONTENT) {
printf("\n");
printf("\n");
}
else {
/* include user SSI footer */
include_ssi_files(COMMAND_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
}
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
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) {
x++;
continue;
}
/* we found the command type */
else if(!strcmp(variables[x], "cmd_typ")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
command_type = atoi(variables[x]);
}
/* we found the command mode */
else if(!strcmp(variables[x], "cmd_mod")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
command_mode = atoi(variables[x]);
}
/* we found the comment id */
else if(!strcmp(variables[x], "com_id")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
comment_id = strtoul(variables[x], NULL, 10);
}
/* we found the downtime id */
else if(!strcmp(variables[x], "down_id")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
downtime_id = strtoul(variables[x], NULL, 10);
}
/* we found the notification delay */
else if(!strcmp(variables[x], "not_dly")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
notification_delay = atoi(variables[x]);
}
/* we found the schedule delay */
else if(!strcmp(variables[x], "sched_dly")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
schedule_delay = atoi(variables[x]);
}
/* we found the comment author */
else if(!strcmp(variables[x], "com_author")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((comment_author = (char *)strdup(variables[x])) == NULL)
comment_author = "";
strip_html_brackets(comment_author);
}
/* we found the comment data */
else if(!strcmp(variables[x], "com_data")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((comment_data = (char *)strdup(variables[x])) == NULL)
comment_data = "";
strip_html_brackets(comment_data);
}
/* we found the host name */
else if(!strcmp(variables[x], "host")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((host_name = (char *)strdup(variables[x])) == NULL)
host_name = "";
strip_html_brackets(host_name);
}
/* we found the hostgroup name */
else if(!strcmp(variables[x], "hostgroup")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((hostgroup_name = (char *)strdup(variables[x])) == NULL)
hostgroup_name = "";
strip_html_brackets(hostgroup_name);
}
/* we found the service name */
else if(!strcmp(variables[x], "service")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((service_desc = (char *)strdup(variables[x])) == NULL)
service_desc = "";
strip_html_brackets(service_desc);
}
/* we found the servicegroup name */
else if(!strcmp(variables[x], "servicegroup")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((servicegroup_name = (char *)strdup(variables[x])) == NULL)
servicegroup_name = "";
strip_html_brackets(servicegroup_name);
}
/* we got the persistence option for a comment */
else if(!strcmp(variables[x], "persistent"))
persistent_comment = TRUE;
/* we got the notification option for an acknowledgement */
else if(!strcmp(variables[x], "send_notification"))
send_notification = TRUE;
/* we got the acknowledgement type */
else if(!strcmp(variables[x], "sticky_ack"))
sticky_ack = TRUE;
/* we got the service check force option */
else if(!strcmp(variables[x], "force_check"))
force_check = TRUE;
/* we got the option to affect host and all its services */
else if(!strcmp(variables[x], "ahas"))
affect_host_and_services = TRUE;
/* we got the option to propagate to child hosts */
else if(!strcmp(variables[x], "ptc"))
propagate_to_children = TRUE;
/* we got the option for fixed downtime */
else if(!strcmp(variables[x], "fixed")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
fixed = (atoi(variables[x]) > 0) ? TRUE : FALSE;
}
/* we got the triggered by downtime option */
else if(!strcmp(variables[x], "trigger")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
triggered_by = strtoul(variables[x], NULL, 10);
}
/* we got the child options */
else if(!strcmp(variables[x], "childoptions")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
child_options = atoi(variables[x]);
}
/* we found the plugin output */
else if(!strcmp(variables[x], "plugin_output")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
/* protect against buffer overflows */
if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
error = TRUE;
break;
}
else
strcpy(plugin_output, variables[x]);
}
/* we found the performance data */
else if(!strcmp(variables[x], "performance_data")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
/* protect against buffer overflows */
if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
error = TRUE;
break;
}
else
strcpy(performance_data, variables[x]);
}
/* we found the plugin state */
else if(!strcmp(variables[x], "plugin_state")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
plugin_state = atoi(variables[x]);
}
/* we found the hour duration */
else if(!strcmp(variables[x], "hours")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(atoi(variables[x]) < 0) {
error = TRUE;
break;
}
duration += (unsigned long)(atoi(variables[x]) * 3600);
}
/* we found the minute duration */
else if(!strcmp(variables[x], "minutes")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(atoi(variables[x]) < 0) {
error = TRUE;
break;
}
duration += (unsigned long)(atoi(variables[x]) * 60);
}
/* we found the start time */
else if(!strcmp(variables[x], "start_time")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
start_time_string = (char *)malloc(strlen(variables[x]) + 1);
if(start_time_string == NULL)
start_time_string = "";
else
strcpy(start_time_string, variables[x]);
}
/* we found the end time */
else if(!strcmp(variables[x], "end_time")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
end_time_string = (char *)malloc(strlen(variables[x]) + 1);
if(end_time_string == NULL)
end_time_string = "";
else
strcpy(end_time_string, variables[x]);
}
/* we found the content type argument */
else if(!strcmp(variables[x], "content")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "wml")) {
content_type = WML_CONTENT;
display_header = FALSE;
}
else
content_type = HTML_CONTENT;
}
/* we found the forced notification option */
else if(!strcmp(variables[x], "force_notification"))
force_notification = NOTIFICATION_OPTION_FORCED;
/* we found the broadcast notification option */
else if(!strcmp(variables[x], "broadcast_notification"))
broadcast_notification = NOTIFICATION_OPTION_BROADCAST;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
void request_command_data(int cmd) {
time_t t;
char start_time[MAX_DATETIME_LENGTH];
char buffer[MAX_INPUT_BUFFER];
contact *temp_contact;
scheduled_downtime *temp_downtime;
/* get default name to use for comment author */
temp_contact = find_contact(current_authdata.username);
if(temp_contact != NULL && temp_contact->alias != NULL)
comment_author = temp_contact->alias;
else
comment_author = current_authdata.username;
printf("
You are requesting to ");
switch(cmd) {
case CMD_ADD_HOST_COMMENT:
case CMD_ADD_SVC_COMMENT:
printf("add a %s comment", (cmd == CMD_ADD_HOST_COMMENT) ? "host" : "service");
break;
case CMD_DEL_HOST_COMMENT:
case CMD_DEL_SVC_COMMENT:
printf("delete a %s comment", (cmd == CMD_DEL_HOST_COMMENT) ? "host" : "service");
break;
case CMD_DELAY_HOST_NOTIFICATION:
case CMD_DELAY_SVC_NOTIFICATION:
printf("delay a %s notification", (cmd == CMD_DELAY_HOST_NOTIFICATION) ? "host" : "service");
break;
case CMD_SCHEDULE_SVC_CHECK:
printf("schedule a service check");
break;
case CMD_ENABLE_SVC_CHECK:
case CMD_DISABLE_SVC_CHECK:
printf("%s active checks of a particular service", (cmd == CMD_ENABLE_SVC_CHECK) ? "enable" : "disable");
break;
case CMD_ENABLE_NOTIFICATIONS:
case CMD_DISABLE_NOTIFICATIONS:
printf("%s notifications", (cmd == CMD_ENABLE_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_SHUTDOWN_PROCESS:
case CMD_RESTART_PROCESS:
printf("%s the Nagios process", (cmd == CMD_SHUTDOWN_PROCESS) ? "shutdown" : "restart");
break;
case CMD_ENABLE_HOST_SVC_CHECKS:
case CMD_DISABLE_HOST_SVC_CHECKS:
printf("%s active checks of all services on a host", (cmd == CMD_ENABLE_HOST_SVC_CHECKS) ? "enable" : "disable");
break;
case CMD_SCHEDULE_HOST_SVC_CHECKS:
printf("schedule a check of all services for a host");
break;
case CMD_DEL_ALL_HOST_COMMENTS:
case CMD_DEL_ALL_SVC_COMMENTS:
printf("delete all comments for a %s", (cmd == CMD_DEL_ALL_HOST_COMMENTS) ? "host" : "service");
break;
case CMD_ENABLE_SVC_NOTIFICATIONS:
case CMD_DISABLE_SVC_NOTIFICATIONS:
printf("%s notifications for a service", (cmd == CMD_ENABLE_SVC_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOST_NOTIFICATIONS:
printf("%s notifications for a host", (cmd == CMD_ENABLE_HOST_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
printf("%s notifications for all hosts and services beyond a host", (cmd == CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST) ? "enable" : "disable");
break;
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
printf("%s notifications for all services on a host", (cmd == CMD_ENABLE_HOST_SVC_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ACKNOWLEDGE_HOST_PROBLEM:
case CMD_ACKNOWLEDGE_SVC_PROBLEM:
printf("acknowledge a %s problem", (cmd == CMD_ACKNOWLEDGE_HOST_PROBLEM) ? "host" : "service");
break;
case CMD_START_EXECUTING_SVC_CHECKS:
case CMD_STOP_EXECUTING_SVC_CHECKS:
printf("%s executing active service checks", (cmd == CMD_START_EXECUTING_SVC_CHECKS) ? "start" : "stop");
break;
case CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS:
printf("%s accepting passive service checks", (cmd == CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS) ? "start" : "stop");
break;
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
printf("%s accepting passive service checks for a particular service", (cmd == CMD_ENABLE_PASSIVE_SVC_CHECKS) ? "start" : "stop");
break;
case CMD_ENABLE_EVENT_HANDLERS:
case CMD_DISABLE_EVENT_HANDLERS:
printf("%s event handlers", (cmd == CMD_ENABLE_EVENT_HANDLERS) ? "enable" : "disable");
break;
case CMD_ENABLE_HOST_EVENT_HANDLER:
case CMD_DISABLE_HOST_EVENT_HANDLER:
printf("%s the event handler for a particular host", (cmd == CMD_ENABLE_HOST_EVENT_HANDLER) ? "enable" : "disable");
break;
case CMD_ENABLE_SVC_EVENT_HANDLER:
case CMD_DISABLE_SVC_EVENT_HANDLER:
printf("%s the event handler for a particular service", (cmd == CMD_ENABLE_SVC_EVENT_HANDLER) ? "enable" : "disable");
break;
case CMD_ENABLE_HOST_CHECK:
case CMD_DISABLE_HOST_CHECK:
printf("%s active checks of a particular host", (cmd == CMD_ENABLE_HOST_CHECK) ? "enable" : "disable");
break;
case CMD_STOP_OBSESSING_OVER_SVC_CHECKS:
case CMD_START_OBSESSING_OVER_SVC_CHECKS:
printf("%s obsessing over service checks", (cmd == CMD_STOP_OBSESSING_OVER_SVC_CHECKS) ? "stop" : "start");
break;
case CMD_REMOVE_HOST_ACKNOWLEDGEMENT:
case CMD_REMOVE_SVC_ACKNOWLEDGEMENT:
printf("remove a %s acknowledgement", (cmd == CMD_REMOVE_HOST_ACKNOWLEDGEMENT) ? "host" : "service");
break;
case CMD_SCHEDULE_HOST_DOWNTIME:
case CMD_SCHEDULE_SVC_DOWNTIME:
printf("schedule downtime for a particular %s", (cmd == CMD_SCHEDULE_HOST_DOWNTIME) ? "host" : "service");
break;
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
printf("schedule downtime for all services for a particular host");
break;
case CMD_PROCESS_HOST_CHECK_RESULT:
case CMD_PROCESS_SERVICE_CHECK_RESULT:
printf("submit a passive check result for a particular %s", (cmd == CMD_PROCESS_HOST_CHECK_RESULT) ? "host" : "service");
break;
case CMD_ENABLE_HOST_FLAP_DETECTION:
case CMD_DISABLE_HOST_FLAP_DETECTION:
printf("%s flap detection for a particular host", (cmd == CMD_ENABLE_HOST_FLAP_DETECTION) ? "enable" : "disable");
break;
case CMD_ENABLE_SVC_FLAP_DETECTION:
case CMD_DISABLE_SVC_FLAP_DETECTION:
printf("%s flap detection for a particular service", (cmd == CMD_ENABLE_SVC_FLAP_DETECTION) ? "enable" : "disable");
break;
case CMD_ENABLE_FLAP_DETECTION:
case CMD_DISABLE_FLAP_DETECTION:
printf("%s flap detection for hosts and services", (cmd == CMD_ENABLE_FLAP_DETECTION) ? "enable" : "disable");
break;
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
printf("%s notifications for all services in a particular hostgroup", (cmd == CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
printf("%s notifications for all hosts in a particular hostgroup", (cmd == CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
case CMD_DISABLE_HOSTGROUP_SVC_CHECKS:
printf("%s active checks of all services in a particular hostgroup", (cmd == CMD_ENABLE_HOSTGROUP_SVC_CHECKS) ? "enable" : "disable");
break;
case CMD_DEL_HOST_DOWNTIME:
case CMD_DEL_SVC_DOWNTIME:
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");
break;
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
printf("schedule downtime for all hosts in a particular hostgroup");
break;
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
printf("schedule downtime for all services in a particular hostgroup");
break;
case CMD_START_EXECUTING_HOST_CHECKS:
case CMD_STOP_EXECUTING_HOST_CHECKS:
printf("%s executing host checks", (cmd == CMD_START_EXECUTING_HOST_CHECKS) ? "start" : "stop");
break;
case CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS:
printf("%s accepting passive host checks", (cmd == CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS) ? "start" : "stop");
break;
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
printf("%s accepting passive checks for a particular host", (cmd == CMD_ENABLE_PASSIVE_HOST_CHECKS) ? "start" : "stop");
break;
case CMD_START_OBSESSING_OVER_HOST_CHECKS:
case CMD_STOP_OBSESSING_OVER_HOST_CHECKS:
printf("%s obsessing over host checks", (cmd == CMD_START_OBSESSING_OVER_HOST_CHECKS) ? "start" : "stop");
break;
case CMD_SCHEDULE_HOST_CHECK:
printf("schedule a host check");
break;
case CMD_START_OBSESSING_OVER_SVC:
case CMD_STOP_OBSESSING_OVER_SVC:
printf("%s obsessing over a particular service", (cmd == CMD_START_OBSESSING_OVER_SVC) ? "start" : "stop");
break;
case CMD_START_OBSESSING_OVER_HOST:
case CMD_STOP_OBSESSING_OVER_HOST:
printf("%s obsessing over a particular host", (cmd == CMD_START_OBSESSING_OVER_HOST) ? "start" : "stop");
break;
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
printf("%s notifications for all services in a particular servicegroup", (cmd == CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
printf("%s notifications for all hosts in a particular servicegroup", (cmd == CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
printf("%s active checks of all services in a particular servicegroup", (cmd == CMD_ENABLE_SERVICEGROUP_SVC_CHECKS) ? "enable" : "disable");
break;
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
printf("schedule downtime for all hosts in a particular servicegroup");
break;
case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME:
printf("schedule downtime for all services in a particular servicegroup");
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");
break;
default:
printf("execute an unknown command. Shame on you!
");
return;
}
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Command Options
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
/* show information about the command... */
show_command_help(cmd);
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
Please enter all required information before committing the command. Required fields are marked in red. Failure to supply all required values will result in an error.
");
return;
}
void commit_command_data(int cmd) {
char *error_string = NULL;
int result = OK;
int authorized = FALSE;
service *temp_service;
host *temp_host;
hostgroup *temp_hostgroup;
comment *temp_comment;
scheduled_downtime *temp_downtime;
servicegroup *temp_servicegroup = NULL;
contact *temp_contact = NULL;
/* get authentication information */
get_authentication_information(¤t_authdata);
/* get name to use for author */
if(lock_author_names == TRUE) {
temp_contact = find_contact(current_authdata.username);
if(temp_contact != NULL && temp_contact->alias != NULL)
comment_author = temp_contact->alias;
else
comment_author = current_authdata.username;
}
switch(cmd) {
case CMD_ADD_HOST_COMMENT:
case CMD_ACKNOWLEDGE_HOST_PROBLEM:
/* make sure we have author name, and comment data... */
if(!strcmp(comment_author, "")) {
if(!error_string)
error_string = strdup("Author was not entered");
}
if(!strcmp(comment_data, "")) {
if(!error_string)
error_string = strdup("Comment was not entered");
}
/* clean up the comment data */
clean_comment_data(comment_author);
clean_comment_data(comment_data);
/* see if the user is authorized to issue a command... */
temp_host = find_host(host_name);
if(is_authorized_for_host_commands(temp_host, ¤t_authdata) == TRUE)
authorized = TRUE;
break;
case CMD_ADD_SVC_COMMENT:
case CMD_ACKNOWLEDGE_SVC_PROBLEM:
/* make sure we have author name, and comment data... */
if(!strcmp(comment_author, "")) {
if(!error_string)
error_string = strdup("Author was not entered");
}
if(!strcmp(comment_data, "")) {
if(!error_string)
error_string = strdup("Comment was not entered");
}
/* clean up the comment data */
clean_comment_data(comment_author);
clean_comment_data(comment_data);
/* see if the user is authorized to issue a command... */
temp_service = find_service(host_name, service_desc);
if(is_authorized_for_service_commands(temp_service, ¤t_authdata) == TRUE)
authorized = TRUE;
break;
case CMD_DEL_HOST_COMMENT:
case CMD_DEL_SVC_COMMENT:
/* check the sanity of the comment id */
if(comment_id == 0) {
if(!error_string)
error_string = strdup("Comment id cannot be 0");
}
/* find the comment */
if(cmd == CMD_DEL_HOST_COMMENT)
temp_comment = find_host_comment(comment_id);
else
temp_comment = find_service_comment(comment_id);
/* see if the user is authorized to issue a command... */
if(cmd == CMD_DEL_HOST_COMMENT && temp_comment != NULL) {
temp_host = find_host(temp_comment->host_name);
if(is_authorized_for_host_commands(temp_host, ¤t_authdata) == TRUE)
authorized = TRUE;
}
if(cmd == CMD_DEL_SVC_COMMENT && temp_comment != NULL) {
temp_service = find_service(temp_comment->host_name, temp_comment->service_description);
if(is_authorized_for_service_commands(temp_service, ¤t_authdata) == TRUE)
authorized = TRUE;
}
/* free comment data */
free_comment_data();
break;
case CMD_DEL_HOST_DOWNTIME:
case CMD_DEL_SVC_DOWNTIME:
/* check the sanity of the downtime id */
if(downtime_id == 0) {
if(!error_string)
error_string = strdup("Downtime id cannot be 0");
}
/* find the downtime entry */
if(cmd == CMD_DEL_HOST_DOWNTIME)
temp_downtime = find_host_downtime(downtime_id);
else
temp_downtime = find_service_downtime(downtime_id);
/* see if the user is authorized to issue a command... */
if(cmd == CMD_DEL_HOST_DOWNTIME && temp_downtime != NULL) {
temp_host = find_host(temp_downtime->host_name);
if(is_authorized_for_host_commands(temp_host, ¤t_authdata) == TRUE)
authorized = TRUE;
}
if(cmd == CMD_DEL_SVC_DOWNTIME && temp_downtime != NULL) {
temp_service = find_service(temp_downtime->host_name, temp_downtime->service_description);
if(is_authorized_for_service_commands(temp_service, ¤t_authdata) == TRUE)
authorized = TRUE;
}
/* free downtime data */
free_downtime_data();
break;
case CMD_SCHEDULE_SVC_CHECK:
case CMD_ENABLE_SVC_CHECK:
case CMD_DISABLE_SVC_CHECK:
case CMD_DEL_ALL_SVC_COMMENTS:
case CMD_ENABLE_SVC_NOTIFICATIONS:
case CMD_DISABLE_SVC_NOTIFICATIONS:
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
case CMD_ENABLE_SVC_EVENT_HANDLER:
case CMD_DISABLE_SVC_EVENT_HANDLER:
case CMD_REMOVE_SVC_ACKNOWLEDGEMENT:
case CMD_PROCESS_SERVICE_CHECK_RESULT:
case CMD_SCHEDULE_SVC_DOWNTIME:
case CMD_DELAY_SVC_NOTIFICATION:
case CMD_ENABLE_SVC_FLAP_DETECTION:
case CMD_DISABLE_SVC_FLAP_DETECTION:
case CMD_START_OBSESSING_OVER_SVC:
case CMD_STOP_OBSESSING_OVER_SVC:
/* make sure we have author name and comment data... */
if(cmd == CMD_SCHEDULE_SVC_DOWNTIME) {
if(!strcmp(comment_data, "")) {
if(!error_string)
error_string = strdup("Comment was not entered");
}
else if(!strcmp(comment_author, "")) {
if(!error_string)
error_string = strdup("Author was not entered");
}
}
/* see if the user is authorized to issue a command... */
temp_service = find_service(host_name, service_desc);
if(is_authorized_for_service_commands(temp_service, ¤t_authdata) == TRUE)
authorized = TRUE;
/* make sure we have passive check info (if necessary) */
if(cmd == CMD_PROCESS_SERVICE_CHECK_RESULT && !strcmp(plugin_output, "")) {
if(!error_string)
error_string = strdup("Plugin output cannot be blank");
}
/* make sure we have a notification delay (if necessary) */
if(cmd == CMD_DELAY_SVC_NOTIFICATION && notification_delay <= 0) {
if(!error_string)
error_string = strdup("Notification delay must be greater than 0");
}
/* clean up the comment data if scheduling downtime */
if(cmd == CMD_SCHEDULE_SVC_DOWNTIME) {
clean_comment_data(comment_author);
clean_comment_data(comment_data);
}
/* make sure we have check time (if necessary) */
if(cmd == CMD_SCHEDULE_SVC_CHECK && start_time == (time_t)0) {
if(!error_string)
error_string = strdup("Start time must be non-zero or bad format has been submitted.");
}
/* make sure we have start/end times for downtime (if necessary) */
if(cmd == CMD_SCHEDULE_SVC_DOWNTIME && (start_time == (time_t)0 || end_time == (time_t)0 || end_time < start_time)) {
if(!error_string)
error_string = strdup("Start or end time not valid");
}
break;
case CMD_ENABLE_NOTIFICATIONS:
case CMD_DISABLE_NOTIFICATIONS:
case CMD_SHUTDOWN_PROCESS:
case CMD_RESTART_PROCESS:
case CMD_START_EXECUTING_SVC_CHECKS:
case CMD_STOP_EXECUTING_SVC_CHECKS:
case CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS:
case CMD_ENABLE_EVENT_HANDLERS:
case CMD_DISABLE_EVENT_HANDLERS:
case CMD_START_OBSESSING_OVER_SVC_CHECKS:
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:
case CMD_STOP_EXECUTING_HOST_CHECKS:
case CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS:
case CMD_START_OBSESSING_OVER_HOST_CHECKS:
case CMD_STOP_OBSESSING_OVER_HOST_CHECKS:
/* see if the user is authorized to issue a command... */
if(is_authorized_for_system_commands(¤t_authdata) == TRUE)
authorized = TRUE;
break;
case CMD_ENABLE_HOST_SVC_CHECKS:
case CMD_DISABLE_HOST_SVC_CHECKS:
case CMD_DEL_ALL_HOST_COMMENTS:
case CMD_SCHEDULE_HOST_SVC_CHECKS:
case CMD_ENABLE_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOST_NOTIFICATIONS:
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
case CMD_ENABLE_HOST_EVENT_HANDLER:
case CMD_DISABLE_HOST_EVENT_HANDLER:
case CMD_ENABLE_HOST_CHECK:
case CMD_DISABLE_HOST_CHECK:
case CMD_REMOVE_HOST_ACKNOWLEDGEMENT:
case CMD_SCHEDULE_HOST_DOWNTIME:
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
case CMD_DELAY_HOST_NOTIFICATION:
case CMD_ENABLE_HOST_FLAP_DETECTION:
case CMD_DISABLE_HOST_FLAP_DETECTION:
case CMD_PROCESS_HOST_CHECK_RESULT:
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
case CMD_SCHEDULE_HOST_CHECK:
case CMD_START_OBSESSING_OVER_HOST:
case CMD_STOP_OBSESSING_OVER_HOST:
/* make sure we have author name and comment data... */
if(cmd == CMD_SCHEDULE_HOST_DOWNTIME || cmd == CMD_SCHEDULE_HOST_SVC_DOWNTIME) {
if(!strcmp(comment_data, "")) {
if(!error_string)
error_string = strdup("Comment was not entered");
}
else if(!strcmp(comment_author, "")) {
if(!error_string)
error_string = strdup("Author was not entered");
}
}
/* see if the user is authorized to issue a command... */
temp_host = find_host(host_name);
if(is_authorized_for_host_commands(temp_host, ¤t_authdata) == TRUE)
authorized = TRUE;
/* clean up the comment data if scheduling downtime */
if(cmd == CMD_SCHEDULE_HOST_DOWNTIME || cmd == CMD_SCHEDULE_HOST_SVC_DOWNTIME) {
clean_comment_data(comment_author);
clean_comment_data(comment_data);
}
/* make sure we have a notification delay (if necessary) */
if(cmd == CMD_DELAY_HOST_NOTIFICATION && notification_delay <= 0) {
if(!error_string)
error_string = strdup("Notification delay must be greater than 0");
}
/* make sure we have start/end times for downtime (if necessary) */
if((cmd == CMD_SCHEDULE_HOST_DOWNTIME || cmd == CMD_SCHEDULE_HOST_SVC_DOWNTIME) && (start_time == (time_t)0 || end_time == (time_t)0 || start_time > end_time)) {
if(!error_string)
error_string = strdup("Start or end time not valid");
}
/* make sure we have check time (if necessary) */
if((cmd == CMD_SCHEDULE_HOST_CHECK || cmd == CMD_SCHEDULE_HOST_SVC_CHECKS) && start_time == (time_t)0) {
if(!error_string)
error_string = strdup("Start time must be non-zero or bad format has been submitted.");
}
/* make sure we have passive check info (if necessary) */
if(cmd == CMD_PROCESS_HOST_CHECK_RESULT && !strcmp(plugin_output, "")) {
if(!error_string)
error_string = strdup("Plugin output cannot be blank");
}
break;
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
case CMD_DISABLE_HOSTGROUP_SVC_CHECKS:
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
/* make sure we have author and comment data */
if(cmd == CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME || cmd == CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME) {
if(!strcmp(comment_data, "")) {
if(!error_string)
error_string = strdup("Comment was not entered");
}
else if(!strcmp(comment_author, "")) {
if(!error_string)
error_string = strdup("Author was not entered");
}
}
/* make sure we have start/end times for downtime */
if((cmd == CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME || cmd == CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME) && (start_time == (time_t)0 || end_time == (time_t)0 || start_time > end_time)) {
if(!error_string)
error_string = strdup("Start or end time not valid");
}
/* see if the user is authorized to issue a command... */
temp_hostgroup = find_hostgroup(hostgroup_name);
if(is_authorized_for_hostgroup_commands(temp_hostgroup, ¤t_authdata) == TRUE)
authorized = TRUE;
/* clean up the comment data if scheduling downtime */
if(cmd == CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME || cmd == CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME) {
clean_comment_data(comment_author);
clean_comment_data(comment_data);
}
break;
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME:
/* make sure we have author and comment data */
if(cmd == CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME || cmd == CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME) {
if(!strcmp(comment_data, "")) {
if(!error_string)
error_string = strdup("Comment was not entered");
}
else if(!strcmp(comment_author, "")) {
if(!error_string)
error_string = strdup("Author was not entered");
}
}
/* make sure we have start/end times for downtime */
if((cmd == CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME || cmd == CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME) && (start_time == (time_t)0 || end_time == (time_t)0 || start_time > end_time)) {
if(!error_string)
error_string = strdup("Start or end time not valid");
}
/* see if the user is authorized to issue a command... */
temp_servicegroup = find_servicegroup(servicegroup_name);
if(is_authorized_for_servicegroup_commands(temp_servicegroup, ¤t_authdata) == TRUE)
authorized = TRUE;
break;
case CMD_SEND_CUSTOM_HOST_NOTIFICATION:
case CMD_SEND_CUSTOM_SVC_NOTIFICATION:
/* make sure we have author and comment data */
if(!strcmp(comment_data, "")) {
if(!error_string)
error_string = strdup("Comment was not entered");
}
else if(!strcmp(comment_author, "")) {
if(!error_string)
error_string = strdup("Author was not entered");
}
/* see if the user is authorized to issue a command... */
if(cmd == CMD_SEND_CUSTOM_HOST_NOTIFICATION) {
temp_host = find_host(host_name);
if(is_authorized_for_host_commands(temp_host, ¤t_authdata) == TRUE)
authorized = TRUE;
}
else {
temp_service = find_service(host_name, service_desc);
if(is_authorized_for_service_commands(temp_service, ¤t_authdata) == TRUE)
authorized = TRUE;
}
break;
default:
if(!error_string) error_string = strdup("An error occurred while processing your command!");
}
/* to be safe, we are going to REQUIRE that the authentication functionality is enabled... */
if(use_authentication == FALSE) {
if(content_type == WML_CONTENT)
printf("
Error: Authentication is not enabled!
\n");
else {
printf("
\n");
printf("
Sorry Dave, I can't let you do that...
");
printf("
");
printf("It seems that you have chosen to not use the authentication functionality of the CGIs.
");
printf("I don't want to be personally responsible for what may happen as a result of allowing unauthorized users to issue commands to Nagios,");
printf("so you'll have to disable this safeguard if you are really stubborn and want to invite trouble.
");
printf("Read the section on CGI authentication in the HTML documentation to learn how you can enable authentication and why you should want to.\n");
printf("
\n");
printf("\n");
}
}
/* the user is not authorized to issue the given command */
else if(authorized == FALSE) {
if(content_type == WML_CONTENT)
printf("
Error: You're not authorized to commit that command!
\n");
else {
printf("
Sorry, but you are not authorized to commit the specified command.
\n");
printf("
Read the section of the documentation that deals with authentication and authorization in the CGIs for more information.
\n");
}
}
}
return;
}
__attribute__((format(printf, 2, 3)))
static int cmd_submitf(int id, const char *fmt, ...) {
char cmd[MAX_EXTERNAL_COMMAND_LENGTH];
const char *command;
int len, len2;
va_list ap;
command = extcmd_get_name(id);
/*
* We disallow sending 'CHANGE' commands from the cgi's
* until we do proper session handling to prevent cross-site
* request forgery
*/
if(!command || (strlen(command) > 6 && !memcmp("CHANGE", command, 6)))
return ERROR;
len = snprintf(cmd, sizeof(cmd) - 1, "[%lu] %s;", time(NULL), command);
if(len < 0)
return ERROR;
if(fmt) {
va_start(ap, fmt);
len2 = vsnprintf(&cmd[len], sizeof(cmd) - len - 1, fmt, ap);
va_end(ap);
if(len2 < 0)
return ERROR;
}
return write_command_to_file(cmd);
}
/* commits a command for processing */
int commit_command(int cmd) {
time_t current_time;
time_t scheduled_time;
time_t notification_time;
int result;
/* get the current time */
time(¤t_time);
/* get the scheduled time */
scheduled_time = current_time + (schedule_delay * 60);
/* get the notification time */
notification_time = current_time + (notification_delay * 60);
/*
* these are supposed to be implanted inside the
* completed commands shipped off to nagios and
* must therefore never contain ';'
*/
if(host_name && strchr(host_name, ';'))
return ERROR;
if(service_desc && strchr(service_desc, ';'))
return ERROR;
if(comment_author && strchr(comment_author, ';'))
return ERROR;
if(hostgroup_name && strchr(hostgroup_name, ';'))
return ERROR;
if(servicegroup_name && strchr(servicegroup_name, ';'))
return ERROR;
/* decide how to form the command line... */
switch(cmd) {
/* commands without arguments */
case CMD_START_EXECUTING_SVC_CHECKS:
case CMD_STOP_EXECUTING_SVC_CHECKS:
case CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS:
case CMD_ENABLE_EVENT_HANDLERS:
case CMD_DISABLE_EVENT_HANDLERS:
case CMD_START_OBSESSING_OVER_SVC_CHECKS:
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:
case CMD_STOP_EXECUTING_HOST_CHECKS:
case CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS:
case CMD_START_OBSESSING_OVER_HOST_CHECKS:
case CMD_STOP_OBSESSING_OVER_HOST_CHECKS:
result = cmd_submitf(cmd, NULL);
break;
/** simple host commands **/
case CMD_ENABLE_HOST_FLAP_DETECTION:
case CMD_DISABLE_HOST_FLAP_DETECTION:
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
case CMD_START_OBSESSING_OVER_HOST:
case CMD_STOP_OBSESSING_OVER_HOST:
case CMD_DEL_ALL_HOST_COMMENTS:
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_ENABLE_HOST_EVENT_HANDLER:
case CMD_DISABLE_HOST_EVENT_HANDLER:
case CMD_ENABLE_HOST_CHECK:
case CMD_DISABLE_HOST_CHECK:
case CMD_REMOVE_HOST_ACKNOWLEDGEMENT:
result = cmd_submitf(cmd, "%s", host_name);
break;
/** simple service commands **/
case CMD_ENABLE_SVC_FLAP_DETECTION:
case CMD_DISABLE_SVC_FLAP_DETECTION:
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
case CMD_START_OBSESSING_OVER_SVC:
case CMD_STOP_OBSESSING_OVER_SVC:
case CMD_DEL_ALL_SVC_COMMENTS:
case CMD_ENABLE_SVC_NOTIFICATIONS:
case CMD_DISABLE_SVC_NOTIFICATIONS:
case CMD_ENABLE_SVC_EVENT_HANDLER:
case CMD_DISABLE_SVC_EVENT_HANDLER:
case CMD_ENABLE_SVC_CHECK:
case CMD_DISABLE_SVC_CHECK:
case CMD_REMOVE_SVC_ACKNOWLEDGEMENT:
result = cmd_submitf(cmd, "%s;%s", host_name, service_desc);
break;
case CMD_ADD_HOST_COMMENT:
result = cmd_submitf(cmd, "%s;%d;%s;%s", host_name, persistent_comment, comment_author, comment_data);
break;
case CMD_ADD_SVC_COMMENT:
result = cmd_submitf(cmd, "%s;%s;%d;%s;%s", host_name, service_desc, persistent_comment, comment_author, comment_data);
break;
case CMD_DEL_HOST_COMMENT:
case CMD_DEL_SVC_COMMENT:
result = cmd_submitf(cmd, "%lu", comment_id);
break;
case CMD_DELAY_HOST_NOTIFICATION:
result = cmd_submitf(cmd, "%s;%lu", host_name, notification_time);
break;
case CMD_DELAY_SVC_NOTIFICATION:
result = cmd_submitf(cmd, "%s;%s;%lu", host_name, service_desc, notification_time);
break;
case CMD_SCHEDULE_SVC_CHECK:
case CMD_SCHEDULE_FORCED_SVC_CHECK:
if(force_check == TRUE)
cmd = CMD_SCHEDULE_FORCED_SVC_CHECK;
result = cmd_submitf(cmd, "%s;%s;%lu", host_name, service_desc, start_time);
break;
case CMD_DISABLE_NOTIFICATIONS:
case CMD_ENABLE_NOTIFICATIONS:
case CMD_SHUTDOWN_PROCESS:
case CMD_RESTART_PROCESS:
result = cmd_submitf(cmd, "%lu", scheduled_time);
break;
case CMD_ENABLE_HOST_SVC_CHECKS:
case CMD_DISABLE_HOST_SVC_CHECKS:
result = cmd_submitf(cmd, "%s", host_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_HOST_SVC_CHECKS) ? CMD_ENABLE_HOST_CHECK : CMD_DISABLE_HOST_CHECK;
result |= cmd_submitf(cmd, "%s", host_name);
}
break;
case CMD_SCHEDULE_HOST_SVC_CHECKS:
if(force_check == TRUE)
cmd = CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS;
result = cmd_submitf(cmd, "%s;%lu", host_name, scheduled_time);
break;
case CMD_ENABLE_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOST_NOTIFICATIONS:
if(propagate_to_children == TRUE)
cmd = (cmd == CMD_ENABLE_HOST_NOTIFICATIONS) ? CMD_ENABLE_HOST_AND_CHILD_NOTIFICATIONS : CMD_DISABLE_HOST_AND_CHILD_NOTIFICATIONS;
result = cmd_submitf(cmd, "%s", host_name);
break;
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
result = cmd_submitf(cmd, "%s", host_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_HOST_SVC_NOTIFICATIONS) ? CMD_ENABLE_HOST_NOTIFICATIONS : CMD_DISABLE_HOST_NOTIFICATIONS;
result |= cmd_submitf(cmd, "%s", host_name);
}
break;
case CMD_ACKNOWLEDGE_HOST_PROBLEM:
result = cmd_submitf(cmd, "%s;%d;%d;%d;%s;%s", host_name, (sticky_ack == TRUE) ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL, send_notification, persistent_comment, comment_author, comment_data);
break;
case CMD_ACKNOWLEDGE_SVC_PROBLEM:
result = cmd_submitf(cmd, "%s;%s;%d;%d;%d;%s;%s", host_name, service_desc, (sticky_ack == TRUE) ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL, send_notification, persistent_comment, comment_author, comment_data);
break;
case CMD_PROCESS_SERVICE_CHECK_RESULT:
result = cmd_submitf(cmd, "%s;%s;%d;%s|%s", host_name, service_desc, plugin_state, plugin_output, performance_data);
break;
case CMD_PROCESS_HOST_CHECK_RESULT:
result = cmd_submitf(cmd, "%s;%d;%s|%s", host_name, plugin_state, plugin_output, performance_data);
break;
case CMD_SCHEDULE_HOST_DOWNTIME:
if(child_options == 1)
cmd = CMD_SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME;
else if(child_options == 2)
cmd = CMD_SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME;
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;%lu;%lu;%s;%s", host_name, start_time, end_time, fixed, triggered_by, duration, comment_author, comment_data);
break;
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;%lu;%lu;%s;%s", host_name, start_time, end_time, fixed, triggered_by, duration, comment_author, comment_data);
break;
case CMD_SCHEDULE_SVC_DOWNTIME:
result = cmd_submitf(cmd, "%s;%s;%lu;%lu;%d;%lu;%lu;%s;%s", host_name, service_desc, start_time, end_time, fixed, triggered_by, duration, comment_author, comment_data);
break;
case CMD_DEL_HOST_DOWNTIME:
case CMD_DEL_SVC_DOWNTIME:
result = cmd_submitf(cmd, "%lu", downtime_id);
break;
case CMD_SCHEDULE_HOST_CHECK:
if(force_check == TRUE)
cmd = CMD_SCHEDULE_FORCED_HOST_CHECK;
result = cmd_submitf(cmd, "%s;%lu", host_name, start_time);
break;
case CMD_SEND_CUSTOM_HOST_NOTIFICATION:
result = cmd_submitf(cmd, "%s;%d;%s;%s", host_name, (force_notification | broadcast_notification), comment_author, comment_data);
break;
case CMD_SEND_CUSTOM_SVC_NOTIFICATION:
result = cmd_submitf(cmd, "%s;%s;%d;%s;%s", host_name, service_desc, (force_notification | broadcast_notification), comment_author, comment_data);
break;
/***** HOSTGROUP COMMANDS *****/
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
result = cmd_submitf(cmd, "%s", hostgroup_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS) ? CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS : CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS;
result |= cmd_submitf(cmd, "%s", hostgroup_name);
}
break;
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
result = cmd_submitf(cmd, "%s", hostgroup_name);
break;
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
case CMD_DISABLE_HOSTGROUP_SVC_CHECKS:
result = cmd_submitf(cmd, "%s", hostgroup_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_HOSTGROUP_SVC_CHECKS) ? CMD_ENABLE_HOSTGROUP_HOST_CHECKS : CMD_DISABLE_HOSTGROUP_HOST_CHECKS;
result |= cmd_submitf(cmd, "%s", hostgroup_name);
}
break;
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;0;%lu;%s;%s", hostgroup_name, start_time, end_time, fixed, duration, comment_author, comment_data);
break;
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;0;%lu;%s;%s", hostgroup_name, start_time, end_time, fixed, duration, comment_author, comment_data);
if(affect_host_and_services == TRUE)
result |= cmd_submitf(CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME, "%s;%lu;%lu;%d;0;%lu;%s;%s", hostgroup_name, start_time, end_time, fixed, duration, comment_author, comment_data);
break;
/***** SERVICEGROUP COMMANDS *****/
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
result = cmd_submitf(cmd, "%s", servicegroup_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS) ? CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS : CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS;
result |= cmd_submitf(cmd, "%s", servicegroup_name);
}
break;
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
result = cmd_submitf(cmd, "%s", servicegroup_name);
break;
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
result = cmd_submitf(cmd, "%s", servicegroup_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_SERVICEGROUP_SVC_CHECKS) ? CMD_ENABLE_SERVICEGROUP_HOST_CHECKS : CMD_DISABLE_SERVICEGROUP_HOST_CHECKS;
result |= cmd_submitf(cmd, "%s", servicegroup_name);
}
break;
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;0;%lu;%s;%s", servicegroup_name, start_time, end_time, fixed, duration, comment_author, comment_data);
break;
case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME:
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;0;%lu;%s;%s", servicegroup_name, start_time, end_time, fixed, duration, comment_author, comment_data);
if(affect_host_and_services == TRUE)
result |= cmd_submitf(CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME, "%s;%lu;%lu;%d;0;%lu;%s;%s", servicegroup_name, start_time, end_time, fixed, duration, comment_author, comment_data);
break;
default:
return ERROR;
break;
}
return result;
}
/* write a command entry to the command file */
int write_command_to_file(char *cmd) {
FILE *fp;
struct stat statbuf;
/*
* Commands are not allowed to have newlines in them, as
* that allows malicious users to hand-craft requests that
* bypass the access-restrictions.
*/
if(!cmd || !*cmd || strchr(cmd, '\n'))
return ERROR;
/* bail out if the external command file doesn't exist */
if(stat(command_file, &statbuf)) {
if(content_type == WML_CONTENT)
printf("
Error: Could not stat() external command file!
\n");
else {
printf("
Error: Could not stat() command file '%s'!
\n", command_file);
printf("
");
printf("The external command file may be missing, Nagios may not be running, and/or Nagios may not be checking external commands.\n");
printf("
\n");
}
return ERROR;
}
/* open the command for writing (since this is a pipe, it will really be appended) */
fp = fopen(command_file, "w");
if(fp == NULL) {
if(content_type == WML_CONTENT)
printf("
Error: Could not open command file for update!
\n");
else {
printf("
Error: Could not open command file '%s' for update!
\n", command_file);
printf("
");
printf("The permissions on the external command file and/or directory may be incorrect. Read the FAQs on how to setup proper permissions.\n");
printf("
\n");
}
return ERROR;
}
/* write the command to file */
fprintf(fp, "%s\n", cmd);
/* flush buffer */
fflush(fp);
fclose(fp);
return OK;
}
/* strips out semicolons from comment data */
void clean_comment_data(char *buffer) {
int x;
int y;
y = (int)strlen(buffer);
for(x = 0; x < y; x++) {
if(buffer[x] == ';')
buffer[x] = ' ';
}
return;
}
/* display information about a command */
void show_command_help(cmd) {
printf("
Command Description
\n");
printf("
\n");
printf("
\n");
/* decide what information to print out... */
switch(cmd) {
case CMD_ADD_HOST_COMMENT:
printf("This command is used to add a comment for the specified host. If you work with other administrators, you may find it useful to share information about a host\n");
printf("that is having problems if more than one of you may be working on it. If you do not check the 'persistent' option, the comment will be automatically be deleted\n");
printf("the next time Nagios is restarted.\n");
break;
case CMD_ADD_SVC_COMMENT:
printf("This command is used to add a comment for the specified service. If you work with other administrators, you may find it useful to share information about a host\n");
printf("or service that is having problems if more than one of you may be working on it. If you do not check the 'persistent' option, the comment will automatically be\n");
printf("deleted the next time Nagios is restarted.\n");
break;
case CMD_DEL_HOST_COMMENT:
printf("This command is used to delete a specific host comment.\n");
break;
case CMD_DEL_SVC_COMMENT:
printf("This command is used to delete a specific service comment.\n");
break;
case CMD_DELAY_HOST_NOTIFICATION:
printf("This command is used to delay the next problem notification that is sent out for the specified host. The notification delay will be disregarded if\n");
printf("the host changes state before the next notification is scheduled to be sent out. This command has no effect if the host is currently UP.\n");
break;
case CMD_DELAY_SVC_NOTIFICATION:
printf("This command is used to delay the next problem notification that is sent out for the specified service. The notification delay will be disregarded if\n");
printf("the service changes state before the next notification is scheduled to be sent out. This command has no effect if the service is currently in an OK state.\n");
break;
case CMD_SCHEDULE_SVC_CHECK:
printf("This command is used to schedule the next check of a particular service. Nagios will re-queue the service to be checked at the time you specify.\n");
printf("If you select the force check option, Nagios will force a check of the service regardless of both what time the scheduled check occurs and whether or not checks are enabled for the service.\n");
break;
case CMD_ENABLE_SVC_CHECK:
printf("This command is used to enable active checks of a service.\n");
break;
case CMD_DISABLE_SVC_CHECK:
printf("This command is used to disable active checks of a service.\n");
break;
case CMD_DISABLE_NOTIFICATIONS:
printf("This command is used to disable host and service notifications on a program-wide basis.\n");
break;
case CMD_ENABLE_NOTIFICATIONS:
printf("This command is used to enable host and service notifications on a program-wide basis.\n");
break;
case CMD_SHUTDOWN_PROCESS:
printf("This command is used to shutdown the Nagios process. Note: Once the Nagios has been shutdown, it cannot be restarted via the web interface!\n");
break;
case CMD_RESTART_PROCESS:
printf("This command is used to restart the Nagios process. Executing a restart command is equivalent to sending the process a HUP signal.\n");
printf("All information will be flushed from memory, the configuration files will be re-read, and Nagios will start monitoring with the new configuration information.\n");
break;
case CMD_ENABLE_HOST_SVC_CHECKS:
printf("This command is used to enable active checks of all services associated with the specified host. This does not enable checks of the host unless you check the 'Enable for host too' option.\n");
break;
case CMD_DISABLE_HOST_SVC_CHECKS:
printf("This command is used to disable active checks of all services associated with the specified host. When a service is disabled Nagios will not monitor the service. Doing this will prevent any notifications being sent out for\n");
printf("the specified service while it is disabled. In order to have Nagios check the service in the future you will have to re-enable the service.\n");
printf("Note that disabling service checks may not necessarily prevent notifications from being sent out about the host which those services are associated with. This does not disable checks of the host unless you check the 'Disable for host too' option.\n");
break;
case CMD_SCHEDULE_HOST_SVC_CHECKS:
printf("This command is used to scheduled the next check of all services on the specified host. If you select the force check option, Nagios will force a check of all services on the host regardless of both what time the scheduled checks occur and whether or not checks are enabled for those services.\n");
break;
case CMD_DEL_ALL_HOST_COMMENTS:
printf("This command is used to delete all comments associated with the specified host.\n");
break;
case CMD_DEL_ALL_SVC_COMMENTS:
printf("This command is used to delete all comments associated with the specified service.\n");
break;
case CMD_ENABLE_SVC_NOTIFICATIONS:
printf("This command is used to enable notifications for the specified service. Notifications will only be sent out for the\n");
printf("service state types you defined in your service definition.\n");
break;
case CMD_DISABLE_SVC_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for the specified service. You will have to re-enable notifications\n");
printf("for this service before any alerts can be sent out in the future.\n");
break;
case CMD_ENABLE_HOST_NOTIFICATIONS:
printf("This command is used to enable notifications for the specified host. Notifications will only be sent out for the\n");
printf("host state types you defined in your host definition. Note that this command does not enable notifications\n");
printf("for services associated with this host.\n");
break;
case CMD_DISABLE_HOST_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for the specified host. You will have to re-enable notifications for this host\n");
printf("before any alerts can be sent out in the future. Note that this command does not disable notifications for services associated with this host.\n");
break;
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
printf("This command is used to enable notifications for all hosts and services that lie \"beyond\" the specified host\n");
printf("(from the view of Nagios).\n");
break;
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
printf("This command is used to temporarily prevent notifications from being sent out for all hosts and services that lie\n");
printf("\"beyond\" the specified host (from the view of Nagios).\n");
break;
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
printf("This command is used to enable notifications for all services on the specified host. Notifications will only be sent out for the\n");
printf("service state types you defined in your service definition. This does not enable notifications for the host unless you check the 'Enable for host too' option.\n");
break;
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for all services on the specified host. You will have to re-enable notifications for\n");
printf("all services associated with this host before any alerts can be sent out in the future. This does not prevent notifications from being sent out about the host unless you check the 'Disable for host too' option.\n");
break;
case CMD_ACKNOWLEDGE_HOST_PROBLEM:
printf("This command is used to acknowledge a host problem. When a host problem is acknowledged, future notifications about problems are temporarily disabled until the host changes from its current state.\n");
printf("If you want acknowledgement to disable notifications until the host recovers, check the 'Sticky Acknowledgement' checkbox.\n");
printf("Contacts for this host will receive a notification about the acknowledgement, so they are aware that someone is working on the problem. Additionally, a comment will also be added to the host.\n");
printf("Make sure to enter your name and fill in a brief description of what you are doing in the comment field. If you would like the host comment to remain once the acknowledgement is removed, check\n");
printf("the 'Persistent Comment' checkbox. If you do not want an acknowledgement notification sent out to the appropriate contacts, uncheck the 'Send Notification' checkbox.\n");
break;
case CMD_ACKNOWLEDGE_SVC_PROBLEM:
printf("This command is used to acknowledge a service problem. When a service problem is acknowledged, future notifications about problems are temporarily disabled until the service changes from its current state.\n");
printf("If you want acknowledgement to disable notifications until the service recovers, check the 'Sticky Acknowledgement' checkbox.\n");
printf("Contacts for this service will receive a notification about the acknowledgement, so they are aware that someone is working on the problem. Additionally, a comment will also be added to the service.\n");
printf("Make sure to enter your name and fill in a brief description of what you are doing in the comment field. If you would like the service comment to remain once the acknowledgement is removed, check\n");
printf("the 'Persistent Comment' checkbox. If you do not want an acknowledgement notification sent out to the appropriate contacts, uncheck the 'Send Notification' checkbox.\n");
break;
case CMD_START_EXECUTING_SVC_CHECKS:
printf("This command is used to resume execution of active service checks on a program-wide basis. Individual services which are disabled will still not be checked.\n");
break;
case CMD_STOP_EXECUTING_SVC_CHECKS:
printf("This command is used to temporarily stop Nagios from actively executing any service checks. This will have the side effect of preventing any notifications from being sent out (for any and all services and hosts).\n");
printf("Service checks will not be executed again until you issue a command to resume service check execution.\n");
break;
case CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS:
printf("This command is used to make Nagios start accepting passive service check results that it finds in the external command file\n");
break;
case CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS:
printf("This command is use to make Nagios stop accepting passive service check results that it finds in the external command file. All passive check results that are found will be ignored.\n");
break;
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
printf("This command is used to allow Nagios to accept passive service check results that it finds in the external command file for this particular service.\n");
break;
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
printf("This command is used to stop Nagios accepting passive service check results that it finds in the external command file for this particular service. All passive check results that are found for this service will be ignored.\n");
break;
case CMD_ENABLE_EVENT_HANDLERS:
printf("This command is used to allow Nagios to run host and service event handlers.\n");
break;
case CMD_DISABLE_EVENT_HANDLERS:
printf("This command is used to temporarily prevent Nagios from running any host or service event handlers.\n");
break;
case CMD_ENABLE_SVC_EVENT_HANDLER:
printf("This command is used to allow Nagios to run the service event handler for a particular service when necessary (if one is defined).\n");
break;
case CMD_DISABLE_SVC_EVENT_HANDLER:
printf("This command is used to temporarily prevent Nagios from running the service event handler for a particular service.\n");
break;
case CMD_ENABLE_HOST_EVENT_HANDLER:
printf("This command is used to allow Nagios to run the host event handler for a particular service when necessary (if one is defined).\n");
break;
case CMD_DISABLE_HOST_EVENT_HANDLER:
printf("This command is used to temporarily prevent Nagios from running the host event handler for a particular host.\n");
break;
case CMD_ENABLE_HOST_CHECK:
printf("This command is used to enable active checks of this host.\n");
break;
case CMD_DISABLE_HOST_CHECK:
printf("This command is used to temporarily prevent Nagios from actively checking the status of a particular host. If Nagios needs to check the status of this host, it will assume that it is in the same state that it was in before checks were disabled.\n");
break;
case CMD_START_OBSESSING_OVER_SVC_CHECKS:
printf("This command is used to have Nagios start obsessing over service checks. Read the documentation on distributed monitoring for more information on this.\n");
break;
case CMD_STOP_OBSESSING_OVER_SVC_CHECKS:
printf("This command is used stop Nagios from obsessing over service checks.\n");
break;
case CMD_REMOVE_HOST_ACKNOWLEDGEMENT:
printf("This command is used to remove an acknowledgement for a particular host problem. Once the acknowledgement is removed, notifications may start being\n");
printf("sent out about the host problem. \n");
break;
case CMD_REMOVE_SVC_ACKNOWLEDGEMENT:
printf("This command is used to remove an acknowledgement for a particular service problem. Once the acknowledgement is removed, notifications may start being\n");
printf("sent out about the service problem.\n");
break;
case CMD_PROCESS_SERVICE_CHECK_RESULT:
printf("This command is used to submit a passive check result for a particular service. It is particularly useful for resetting security-related services to OK states once they have been dealt with.\n");
break;
case CMD_PROCESS_HOST_CHECK_RESULT:
printf("This command is used to submit a passive check result for a particular host.\n");
break;
case CMD_SCHEDULE_HOST_DOWNTIME:
printf("This command is used to schedule downtime for a particular host. During the specified downtime, Nagios will not send notifications out about the host.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for this host as it normally would. Scheduled downtimes are preserved\n");
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 the 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 downtime.\n");
break;
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
printf("This command is used to schedule downtime for all services on a particular host. During the specified downtime, Nagios will not send notifications out about the host.\n");
printf("Normally, a host in downtime will not send alerts about any services in a failed state. This option will explicitly set downtime for all services for this host.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for this host as it normally would. Scheduled downtimes are preserved\n");
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 the 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 downtime.\n");
break;
case CMD_SCHEDULE_SVC_DOWNTIME:
printf("This command is used to schedule downtime for a particular service. During the specified downtime, Nagios will not send notifications out about the service.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for this service as it normally would. Scheduled downtimes are preserved\n");
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 the 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 downtime.\n");
break;
case CMD_ENABLE_HOST_FLAP_DETECTION:
printf("This command is used to enable flap detection for a specific host. If flap detection is disabled on a program-wide basis, this will have no effect,\n");
break;
case CMD_DISABLE_HOST_FLAP_DETECTION:
printf("This command is used to disable flap detection for a specific host.\n");
break;
case CMD_ENABLE_SVC_FLAP_DETECTION:
printf("This command is used to enable flap detection for a specific service. If flap detection is disabled on a program-wide basis, this will have no effect,\n");
break;
case CMD_DISABLE_SVC_FLAP_DETECTION:
printf("This command is used to disable flap detection for a specific service.\n");
break;
case CMD_ENABLE_FLAP_DETECTION:
printf("This command is used to enable flap detection for hosts and services on a program-wide basis. Individual hosts and services may have flap detection disabled.\n");
break;
case CMD_DISABLE_FLAP_DETECTION:
printf("This command is used to disable flap detection for hosts and services on a program-wide basis.\n");
break;
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
printf("This command is used to enable notifications for all services in the specified hostgroup. Notifications will only be sent out for the\n");
printf("service state types you defined in your service definitions. This does not enable notifications for the hosts in this hostgroup unless you check the 'Enable for hosts too' option.\n");
break;
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for all services in the specified hostgroup. You will have to re-enable notifications for\n");
printf("all services in this hostgroup before any alerts can be sent out in the future. This does not prevent notifications from being sent out about the hosts in this hostgroup unless you check the 'Disable for hosts too' option.\n");
break;
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
printf("This command is used to enable notifications for all hosts in the specified hostgroup. Notifications will only be sent out for the\n");
printf("host state types you defined in your host definitions.\n");
break;
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for all hosts in the specified hostgroup. You will have to re-enable notifications for\n");
printf("all hosts in this hostgroup before any alerts can be sent out in the future.\n");
break;
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
printf("This command is used to enable active checks of all services in the specified hostgroup. This does not enable active checks of the hosts in the hostgroup unless you check the 'Enable for hosts too' option.\n");
break;
case CMD_DISABLE_HOSTGROUP_SVC_CHECKS:
printf("This command is used to disable active checks of all services in the specified hostgroup. This does not disable checks of the hosts in the hostgroup unless you check the 'Disable for hosts too' option.\n");
break;
case CMD_DEL_HOST_DOWNTIME:
printf("This command is used to cancel active or pending scheduled downtime for the specified host.\n");
break;
case CMD_DEL_SVC_DOWNTIME:
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;
case CMD_DISABLE_PERFORMANCE_DATA:
printf("This command is used to disable the processing of performance data for hosts and services on a program-wide basis.\n");
break;
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
printf("This command is used to schedule downtime for all hosts in a particular hostgroup. During the specified downtime, Nagios will not send notifications out about the hosts.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for the hosts as it normally would. Scheduled downtimes are preserved\n");
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");
break;
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
printf("This command is used to schedule downtime for all services in a particular hostgroup. During the specified downtime, Nagios will not send notifications out about the services.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for the services as it normally would. Scheduled downtimes are preserved\n");
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("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;
case CMD_START_EXECUTING_HOST_CHECKS:
printf("This command is used to enable active host checks on a program-wide basis.\n");
break;
case CMD_STOP_EXECUTING_HOST_CHECKS:
printf("This command is used to disable active host checks on a program-wide basis.\n");
break;
case CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS:
printf("This command is used to have Nagios start obsessing over host checks. Read the documentation on distributed monitoring for more information on this.\n");
break;
case CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS:
printf("This command is used to stop Nagios from obsessing over host checks.\n");
break;
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
printf("This command is used to allow Nagios to accept passive host check results that it finds in the external command file for a particular host.\n");
break;
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
printf("This command is used to stop Nagios from accepting passive host check results that it finds in the external command file for a particular host. All passive check results that are found for this host will be ignored.\n");
break;
case CMD_START_OBSESSING_OVER_HOST_CHECKS:
printf("This command is used to have Nagios start obsessing over host checks. Read the documentation on distributed monitoring for more information on this.\n");
break;
case CMD_STOP_OBSESSING_OVER_HOST_CHECKS:
printf("This command is used to stop Nagios from obsessing over host checks.\n");
break;
case CMD_SCHEDULE_HOST_CHECK:
printf("This command is used to schedule the next check of a particular host. Nagios will re-queue the host to be checked at the time you specify.\n");
printf("If you select the force check option, Nagios will force a check of the host regardless of both what time the scheduled check occurs and whether or not checks are enabled for the host.\n");
break;
case CMD_START_OBSESSING_OVER_SVC:
printf("This command is used to have Nagios start obsessing over a particular service.\n");
break;
case CMD_STOP_OBSESSING_OVER_SVC:
printf("This command is used to stop Nagios from obsessing over a particular service.\n");
break;
case CMD_START_OBSESSING_OVER_HOST:
printf("This command is used to have Nagios start obsessing over a particular host.\n");
break;
case CMD_STOP_OBSESSING_OVER_HOST:
printf("This command is used to stop Nagios from obsessing over a particular host.\n");
break;
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
printf("This command is used to enable notifications for all services in the specified servicegroup. Notifications will only be sent out for the\n");
printf("service state types you defined in your service definitions. This does not enable notifications for the hosts in this servicegroup unless you check the 'Enable for hosts too' option.\n");
break;
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for all services in the specified servicegroup. You will have to re-enable notifications for\n");
printf("all services in this servicegroup before any alerts can be sent out in the future. This does not prevent notifications from being sent out about the hosts in this servicegroup unless you check the 'Disable for hosts too' option.\n");
break;
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
printf("This command is used to enable notifications for all hosts in the specified servicegroup. Notifications will only be sent out for the\n");
printf("host state types you defined in your host definitions.\n");
break;
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for all hosts in the specified servicegroup. You will have to re-enable notifications for\n");
printf("all hosts in this servicegroup before any alerts can be sent out in the future.\n");
break;
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
printf("This command is used to enable active checks of all services in the specified servicegroup. This does not enable active checks of the hosts in the servicegroup unless you check the 'Enable for hosts too' option.\n");
break;
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
printf("This command is used to disable active checks of all services in the specified servicegroup. This does not disable checks of the hosts in the servicegroup unless you check the 'Disable for hosts too' option.\n");
break;
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
printf("This command is used to schedule downtime for all hosts in a particular servicegroup. During the specified downtime, Nagios will not send notifications out about the hosts.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for the hosts as it normally would. Scheduled downtimes are preserved\n");
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");
break;
case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME:
printf("This command is used to schedule downtime for all services in a particular servicegroup. During the specified downtime, Nagios will not send notifications out about the services.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for the services as it normally would. Scheduled downtimes are preserved\n");
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("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_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");
printf("Custom notifications normally follow the regular notification logic in Nagios. Selecting the Forced option will force the notification to be sent out, regardless of the time restrictions, whether or not notifications are enabled, etc. Selecting the Broadcast option causes the notification to be sent out to all normal (non-escalated) and escalated contacts. These options allow you to override the normal notification logic if you need to get an important message out.\n");
break;
default:
printf("Sorry, but no information is available for this command.");
}
printf("
\n");
printf("
\n");
return;
}
/* converts a time string to a UNIX timestamp, respecting the date_format option */
int string_to_time(char *buffer, time_t *t) {
struct tm lt;
int ret = 0;
/* Initialize some variables just in case they don't get parsed
by the sscanf() call. A better solution is to also check the
CGI input for validity, but this should suffice to prevent
strange problems if the input is not valid.
Jan 15 2003 Steve Bonds */
lt.tm_mon = 0;
lt.tm_mday = 1;
lt.tm_year = 1900;
lt.tm_hour = 0;
lt.tm_min = 0;
lt.tm_sec = 0;
lt.tm_wday = 0;
lt.tm_yday = 0;
if(date_format == DATE_FORMAT_EURO)
ret = sscanf(buffer, "%02d-%02d-%04d %02d:%02d:%02d", <.tm_mday, <.tm_mon, <.tm_year, <.tm_hour, <.tm_min, <.tm_sec);
else if(date_format == DATE_FORMAT_ISO8601 || date_format == DATE_FORMAT_STRICT_ISO8601)
ret = sscanf(buffer, "%04d-%02d-%02d%*[ T]%02d:%02d:%02d", <.tm_year, <.tm_mon, <.tm_mday, <.tm_hour, <.tm_min, <.tm_sec);
else
ret = sscanf(buffer, "%02d-%02d-%04d %02d:%02d:%02d", <.tm_mon, <.tm_mday, <.tm_year, <.tm_hour, <.tm_min, <.tm_sec);
if(ret != 6)
return ERROR;
lt.tm_mon--;
lt.tm_year -= 1900;
/* tell mktime() to try and compute DST automatically */
lt.tm_isdst = -1;
*t = mktime(<);
return OK;
}
nagios/cgi/config.c 0000664 0000000 0000000 00000256172 12210155146 0014523 0 ustar 00root root 0000000 0000000 /***********************************************************************
*
* 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.
*
*
* 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/macros.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
#include "../include/getcgi.h"
static nagios_macros *mac;
extern char main_config_file[MAX_FILENAME_LENGTH];
extern char url_html_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 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
#define DISPLAY_CONTACTS 3
#define DISPLAY_CONTACTGROUPS 4
#define DISPLAY_SERVICES 5
#define DISPLAY_TIMEPERIODS 6
#define DISPLAY_COMMANDS 7
#define DISPLAY_HOSTGROUPESCALATIONS 8 /* no longer implemented */
#define DISPLAY_SERVICEDEPENDENCIES 9
#define DISPLAY_SERVICEESCALATIONS 10
#define DISPLAY_HOSTDEPENDENCIES 11
#define DISPLAY_HOSTESCALATIONS 12
#define DISPLAY_SERVICEGROUPS 15
#define DISPLAY_COMMAND_EXPANSION 16211
void document_header(int);
void document_footer(void);
int process_cgivars(void);
void display_options(void);
void display_hosts(void);
void display_hostgroups(void);
void display_servicegroups(void);
void display_contacts(void);
void display_contactgroups(void);
void display_services(void);
void display_timeperiods(void);
void display_commands(void);
void display_servicedependencies(void);
void display_serviceescalations(void);
void display_hostdependencies(void);
void display_hostescalations(void);
void display_command_expansion(void);
void unauthorized_message(void);
authdata current_authdata;
int display_type = DISPLAY_NONE;
char to_expand[MAX_COMMAND_BUFFER];
char hashed_color[8];
int embedded = FALSE;
void print_expand_input(int type) {
char *seldesc = "";
if(type == DISPLAY_COMMAND_EXPANSION) return; /* Has its own form, w/ larger */
else if(type == DISPLAY_SERVICES) {
seldesc = " Services Named or on Host";
}
else if(type == DISPLAY_SERVICEDEPENDENCIES) {
seldesc = " Dependencies with Host";
}
else if(type == DISPLAY_SERVICEESCALATIONS) {
seldesc = " Escalations on Host";
}
else if(type == DISPLAY_HOSTDEPENDENCIES) {
seldesc = " Dependencies on/of Host";
}
else if(type == DISPLAY_HOSTESCALATIONS) {
seldesc = " Escalations for Host";
}
printf("
Show Only%s:
\n", seldesc);
printf("
", html_encode(to_expand, FALSE));
}
int main(void) {
int result = OK;
mac = get_global_macros();
/* 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;
}
/* initialize macros */
init_macros();
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_authdata);
/* begin top table */
printf("
\n");
if(display_type != DISPLAY_NONE) {
printf("\n");
}
/* display context-sensitive help */
switch(display_type) {
case DISPLAY_HOSTS:
display_context_help(CONTEXTHELP_CONFIG_HOSTS);
break;
case DISPLAY_HOSTGROUPS:
display_context_help(CONTEXTHELP_CONFIG_HOSTGROUPS);
break;
case DISPLAY_SERVICEGROUPS:
display_context_help(CONTEXTHELP_CONFIG_SERVICEGROUPS);
break;
case DISPLAY_CONTACTS:
display_context_help(CONTEXTHELP_CONFIG_CONTACTS);
break;
case DISPLAY_CONTACTGROUPS:
display_context_help(CONTEXTHELP_CONFIG_CONTACTGROUPS);
break;
case DISPLAY_SERVICES:
display_context_help(CONTEXTHELP_CONFIG_SERVICES);
break;
case DISPLAY_TIMEPERIODS:
display_context_help(CONTEXTHELP_CONFIG_TIMEPERIODS);
break;
case DISPLAY_COMMANDS:
display_context_help(CONTEXTHELP_CONFIG_COMMANDS);
break;
case DISPLAY_SERVICEDEPENDENCIES:
display_context_help(CONTEXTHELP_CONFIG_SERVICEDEPENDENCIES);
break;
case DISPLAY_SERVICEESCALATIONS:
display_context_help(CONTEXTHELP_CONFIG_HOSTESCALATIONS);
break;
case DISPLAY_HOSTDEPENDENCIES:
display_context_help(CONTEXTHELP_CONFIG_HOSTDEPENDENCIES);
break;
case DISPLAY_HOSTESCALATIONS:
display_context_help(CONTEXTHELP_CONFIG_HOSTESCALATIONS);
break;
case DISPLAY_COMMAND_EXPANSION:
/* Reusing DISPLAY_COMMANDS help until further notice */
display_context_help(CONTEXTHELP_CONFIG_COMMANDS);
break;
default:
display_context_help(CONTEXTHELP_CONFIG_MENU);
break;
}
printf("
\n");
/* end of top table */
printf("
\n");
printf("
\n");
switch(display_type) {
case DISPLAY_HOSTS:
display_hosts();
break;
case DISPLAY_HOSTGROUPS:
display_hostgroups();
break;
case DISPLAY_SERVICEGROUPS:
display_servicegroups();
break;
case DISPLAY_CONTACTS:
display_contacts();
break;
case DISPLAY_CONTACTGROUPS:
display_contactgroups();
break;
case DISPLAY_SERVICES:
display_services();
break;
case DISPLAY_TIMEPERIODS:
display_timeperiods();
break;
case DISPLAY_COMMANDS:
display_commands();
break;
case DISPLAY_SERVICEDEPENDENCIES:
display_servicedependencies();
break;
case DISPLAY_SERVICEESCALATIONS:
display_serviceescalations();
break;
case DISPLAY_HOSTDEPENDENCIES:
display_hostdependencies();
break;
case DISPLAY_HOSTESCALATIONS:
display_hostescalations();
break;
case DISPLAY_COMMAND_EXPANSION:
display_command_expansion();
break;
default:
display_options();
break;
}
document_footer();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t t;
if(embedded == TRUE)
return;
time(&t);
get_time_string(&t, date_time, sizeof(date_time), HTTP_DATE_TIME);
printf("Cache-Control: no-store\r\n");
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("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("\n");
printf("Configuration\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("\n", url_stylesheets_path, COMMON_CSS);
printf("\n", url_stylesheets_path, CONFIG_CSS);
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(CONFIG_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(CONFIG_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
to_expand[0] = '\0';
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) {
x++;
continue;
}
/* we found the configuration type argument */
else if(!strcmp(variables[x], "type")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
/* what information should we display? */
if(!strcmp(variables[x], "hosts"))
display_type = DISPLAY_HOSTS;
else if(!strcmp(variables[x], "hostgroups"))
display_type = DISPLAY_HOSTGROUPS;
else if(!strcmp(variables[x], "servicegroups"))
display_type = DISPLAY_SERVICEGROUPS;
else if(!strcmp(variables[x], "contacts"))
display_type = DISPLAY_CONTACTS;
else if(!strcmp(variables[x], "contactgroups"))
display_type = DISPLAY_CONTACTGROUPS;
else if(!strcmp(variables[x], "services"))
display_type = DISPLAY_SERVICES;
else if(!strcmp(variables[x], "timeperiods"))
display_type = DISPLAY_TIMEPERIODS;
else if(!strcmp(variables[x], "commands"))
display_type = DISPLAY_COMMANDS;
else if(!strcmp(variables[x], "servicedependencies"))
display_type = DISPLAY_SERVICEDEPENDENCIES;
else if(!strcmp(variables[x], "serviceescalations"))
display_type = DISPLAY_SERVICEESCALATIONS;
else if(!strcmp(variables[x], "hostdependencies"))
display_type = DISPLAY_HOSTDEPENDENCIES;
else if(!strcmp(variables[x], "hostescalations"))
display_type = DISPLAY_HOSTESCALATIONS;
else if(!strcmp(variables[x], "command"))
display_type = DISPLAY_COMMAND_EXPANSION;
/* we found the embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
}
/* we found the string-to-expand argument */
else if(!strcmp(variables[x], "expand")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
strncpy(to_expand, variables[x], MAX_COMMAND_BUFFER);
to_expand[MAX_COMMAND_BUFFER - 1] = '\0';
}
/* we received an invalid argument */
else
error = TRUE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
void display_hosts(void) {
host *temp_host = NULL;
hostsmember *temp_hostsmember = NULL;
contactsmember *temp_contactsmember = NULL;
contactgroupsmember *temp_contactgroupsmember = NULL;
char *processed_string = NULL;
int options = 0;
int odd = 0;
char time_string[16];
char *bg_class = "";
int contact = 0;
/* see if user is authorized to view host information... */
if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) {
unauthorized_message();
return;
}
printf("
It appears as though you do not have permission to view the configuration information 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");
return;
}
char *hash_color(int i) {
char c;
/* This is actually optimized for MAX_COMMAND_ARGUMENTS==32 ... */
if((i % 32) < 16) {
if((i % 32) < 8) c = '7';
else c = '4';
}
else {
if((i % 32) < 24) c = '6';
else c = '5';
}
/* Computation for standard case */
hashed_color[0] = '#';
hashed_color[1] = hashed_color[2] = ((i % 2) ? c : '0');
hashed_color[3] = hashed_color[4] = (((i / 2) % 2) ? c : '0');
hashed_color[5] = hashed_color[6] = (((i / 4) % 2) ? c : '0');
hashed_color[7] = '\0';
/* Override shades of grey */
if((i % 8) == 7) hashed_color[1] = hashed_color[3] = '0';
if((i % 8) == 0) hashed_color[2] = hashed_color[3] = hashed_color[4] = hashed_color[6] = c;
return(hashed_color);
}
void display_command_expansion(void) {
command *temp_command;
int odd = 0;
char *bg_class = "";
int i, j;
char *c, *cc;
char commandline[MAX_COMMAND_BUFFER];
char *command_args[MAX_COMMAND_ARGUMENTS];
int arg_count[MAX_COMMAND_ARGUMENTS],
lead_space[MAX_COMMAND_ARGUMENTS],
trail_space[MAX_COMMAND_ARGUMENTS];
/* see if user is authorized to view command information... */
if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) {
unauthorized_message();
return;
}
printf("
Command Expansion
\n");
/* Parse to_expand into parts */
for(i = 0; i < MAX_COMMAND_ARGUMENTS; i++) command_args[i] = NULL;
for(i = 0, command_args[0] = cc = c = strdup(to_expand); c && ((*c) != '\0') && (i < MAX_COMMAND_ARGUMENTS); c++, cc++) {
if((*c) == '\\') c++;
else if((*c) == '!') {
(*cc) = '\0';
cc = c++;
command_args[++i] = (c--);
}
(*cc) = (*c);
}
if((*c) == '\0')(*cc) = '\0';
/* Precompute indexes of dangling whitespace */
for(i = 0; i < MAX_COMMAND_ARGUMENTS; i++) {
for(cc = command_args[i], lead_space[i] = 0; cc && isspace(*cc); cc++, lead_space[i]++) ;
trail_space[i] = 0;
for(; cc && ((*cc) != '\0'); cc++) if(isspace(*cc)) trail_space[i]++;
else trail_space[i] = 0;
}
printf("
\n");
}
printf(" \n");
if(display_type == DISPLAY_HOST_INFO)
show_host_info();
else if(display_type == DISPLAY_SERVICE_INFO)
show_service_info();
else if(display_type == DISPLAY_COMMENTS)
show_all_comments();
else if(display_type == DISPLAY_PERFORMANCE)
show_performance_data();
else if(display_type == DISPLAY_HOSTGROUP_INFO)
show_hostgroup_info();
else if(display_type == DISPLAY_SERVICEGROUP_INFO)
show_servicegroup_info();
else if(display_type == DISPLAY_DOWNTIME)
show_all_downtime();
else if(display_type == DISPLAY_SCHEDULING_QUEUE)
show_scheduling_queue();
else
show_process_info();
document_footer();
/* free all allocated memory */
free_memory();
free_comment_data();
free_downtime_data();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
time_t expire_time;
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
printf("Refresh: %d\r\n", refresh_rate);
time(¤t_time);
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: text/html\r\n\r\n");
if(embedded == TRUE)
return;
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("Extended Information\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("", url_stylesheets_path, COMMON_CSS);
printf("", url_stylesheets_path, EXTINFO_CSS);
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(EXTINFO_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(EXTINFO_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int temp_type;
int x;
variables = getcgivars();
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) {
x++;
continue;
}
/* we found the display type */
else if(!strcmp(variables[x], "type")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
temp_type = atoi(variables[x]);
if(temp_type == DISPLAY_HOST_INFO)
display_type = DISPLAY_HOST_INFO;
else if(temp_type == DISPLAY_SERVICE_INFO)
display_type = DISPLAY_SERVICE_INFO;
else if(temp_type == DISPLAY_COMMENTS)
display_type = DISPLAY_COMMENTS;
else if(temp_type == DISPLAY_PERFORMANCE)
display_type = DISPLAY_PERFORMANCE;
else if(temp_type == DISPLAY_HOSTGROUP_INFO)
display_type = DISPLAY_HOSTGROUP_INFO;
else if(temp_type == DISPLAY_SERVICEGROUP_INFO)
display_type = DISPLAY_SERVICEGROUP_INFO;
else if(temp_type == DISPLAY_DOWNTIME)
display_type = DISPLAY_DOWNTIME;
else if(temp_type == DISPLAY_SCHEDULING_QUEUE)
display_type = DISPLAY_SCHEDULING_QUEUE;
else
display_type = DISPLAY_PROCESS_INFO;
}
/* we found the host name */
else if(!strcmp(variables[x], "host")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
host_name = strdup(variables[x]);
if(host_name == NULL)
host_name = "";
strip_html_brackets(host_name);
}
/* we found the hostgroup name */
else if(!strcmp(variables[x], "hostgroup")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
hostgroup_name = strdup(variables[x]);
if(hostgroup_name == NULL)
hostgroup_name = "";
strip_html_brackets(hostgroup_name);
}
/* we found the service name */
else if(!strcmp(variables[x], "service")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
service_desc = strdup(variables[x]);
if(service_desc == NULL)
service_desc = "";
strip_html_brackets(service_desc);
}
/* we found the servicegroup name */
else if(!strcmp(variables[x], "servicegroup")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
servicegroup_name = strdup(variables[x]);
if(servicegroup_name == NULL)
servicegroup_name = "";
strip_html_brackets(servicegroup_name);
}
/* we found the sort type argument */
else if(!strcmp(variables[x], "sorttype")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
sort_type = atoi(variables[x]);
}
/* we found the sort option argument */
else if(!strcmp(variables[x], "sortoption")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
sort_option = atoi(variables[x]);
}
/* we found the embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
/* we found the noheader option */
else if(!strcmp(variables[x], "noheader"))
display_header = FALSE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
void show_process_info(void) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
unsigned long run_time;
char run_time_string[24];
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
/* make sure the user has rights to view system information */
if(is_authorized_for_system_information(¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view process information...
\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");
return;
}
printf(" \n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Process Information
\n");
printf("
\n");
printf("
\n");
printf("
\n");
/* program version */
printf("
Program Version:
%s
\n", PROGRAM_VERSION);
/* program start time */
get_time_string(&program_start, date_time, (int)sizeof(date_time), SHORT_DATE_TIME);
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");
}
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
}
void show_host_info(void) {
hoststatus *temp_hoststatus;
host *temp_host;
char date_time[MAX_DATETIME_LENGTH];
char state_duration[48];
char status_age[48];
char state_string[MAX_INPUT_BUFFER];
char *bg_class = "";
char *buf = NULL;
int days;
int hours;
int minutes;
int seconds;
time_t current_time;
time_t t;
int duration_error = FALSE;
/* get host info */
temp_host = find_host(host_name);
/* make sure the user has rights to view host information */
if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view information for this host...
\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");
return;
}
/* get host status info */
temp_hoststatus = find_hoststatus(host_name);
/* make sure host information exists */
if(temp_host == NULL) {
printf("
\n");
printf("\n");
return;
}
void show_service_info(void) {
service *temp_service;
char date_time[MAX_DATETIME_LENGTH];
char status_age[48];
char state_duration[48];
servicestatus *temp_svcstatus;
char state_string[MAX_INPUT_BUFFER];
char *bg_class = "";
char *buf = NULL;
int days;
int hours;
int minutes;
int seconds;
time_t t;
time_t current_time;
int duration_error = FALSE;
/* find the service */
temp_service = find_service(host_name, service_desc);
/* make sure the user has rights to view service information */
if(is_authorized_for_service(temp_service, ¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view information for this service...
\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");
return;
}
/* get service status info */
temp_svcstatus = find_servicestatus(host_name, service_desc);
/* make sure service information exists */
if(temp_service == NULL) {
printf("
\n");
return;
}
void show_hostgroup_info(void) {
hostgroup *temp_hostgroup;
/* get hostgroup info */
temp_hostgroup = find_hostgroup(hostgroup_name);
/* make sure the user has rights to view hostgroup information */
if(is_authorized_for_hostgroup(temp_hostgroup, ¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view information for this hostgroup...
\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");
return;
}
/* make sure hostgroup information exists */
if(temp_hostgroup == NULL) {
printf("
\n");
return;
}
void show_servicegroup_info() {
servicegroup *temp_servicegroup;
/* get servicegroup info */
temp_servicegroup = find_servicegroup(servicegroup_name);
/* make sure the user has rights to view servicegroup information */
if(is_authorized_for_servicegroup(temp_servicegroup, ¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view information for this servicegroup...
\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");
return;
}
/* make sure servicegroup information exists */
if(temp_servicegroup == NULL) {
printf("
\n");
/***** ACTIVE SERVICE CHECKS *****/
printf("
\n");
printf("
Services Actively Checked:
\n");
printf("
\n");
/* fake this so we don't divide by zero for just showing the table */
if(total_active_service_checks == 0)
total_active_service_checks = 1;
printf("
\n");
/***** PASSIVE SERVICE CHECKS *****/
printf("
\n");
printf("
Services Passively Checked:
\n");
printf("
\n");
/* fake this so we don't divide by zero for just showing the table */
if(total_passive_service_checks == 0)
total_passive_service_checks = 1;
printf("
\n");
return;
}
/* shows all service and host scheduled downtime */
void show_all_downtime(void) {
int total_downtime = 0;
char *bg_class = "";
int odd = 0;
char date_time[MAX_DATETIME_LENGTH];
scheduled_downtime *temp_downtime;
host *temp_host;
service *temp_service;
int days;
int hours;
int minutes;
int seconds;
printf(" \n");
printf("
\n");
return;
}
/* shows check scheduling queue */
void show_scheduling_queue(void) {
sortdata *temp_sortdata;
servicestatus *temp_svcstatus = NULL;
hoststatus *temp_hststatus = NULL;
char date_time[MAX_DATETIME_LENGTH];
char temp_url[MAX_INPUT_BUFFER];
int odd = 0;
char *bgclass = "";
/* make sure the user has rights to view system information */
if(is_authorized_for_system_information(¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view process information...
\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.
No history information was found ");
if(display_type == DISPLAY_HOSTS)
printf("%s", (show_all_hosts == TRUE) ? "" : "for this host ");
else
printf("for this service ");
printf("in %s log file
", (log_archive == 0) ? "the current" : "this archived");
}
printf("\n");
my_free(input);
my_free(input2);
if(use_lifo == TRUE)
free_lifo_memory();
else
mmap_fclose(thefile);
return;
}
nagios/cgi/notifications.c 0000664 0000000 0000000 00000063022 12210155146 0016115 0 ustar 00root root 0000000 0000000 /************************************************************************
*
* 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.
*
* 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/getcgi.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
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_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
#define FIND_SERVICE 3
#define MAX_QUERYNAME_LENGTH 256
#define SERVICE_NOTIFICATION 0
#define HOST_NOTIFICATION 1
#define SERVICE_NOTIFICATION_STRING "] SERVICE NOTIFICATION:"
#define HOST_NOTIFICATION_STRING "] HOST NOTIFICATION:"
void display_notifications(void);
void document_header(int);
void document_footer(void);
int process_cgivars(void);
authdata current_authdata;
char log_file_to_use[MAX_FILENAME_LENGTH];
int log_archive = 0;
int query_type = FIND_HOST;
int find_all = TRUE;
char *query_contact_name = "";
char *query_host_name = "";
char *query_svc_description = "";
int notification_options = NOTIFICATION_ALL;
int use_lifo = TRUE;
int embedded = FALSE;
int display_header = TRUE;
int main(void) {
int result = OK;
char temp_buffer[MAX_INPUT_BUFFER];
char temp_buffer2[MAX_INPUT_BUFFER];
/* 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;
}
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_authdata);
/* determine what log file we should use */
get_log_archive_to_use(log_archive, log_file_to_use, (int)sizeof(log_file_to_use));
if(display_header == TRUE) {
/* begin top table */
printf("
No notifications have been recorded");
if(find_all == FALSE) {
if(query_type == FIND_SERVICE)
printf(" for this service");
else if(query_type == FIND_CONTACT)
printf(" for this contact");
else
printf(" for this host");
}
printf(" in %s log file
", (log_archive == 0) ? "the current" : "this archived");
}
free(input);
if(use_lifo == TRUE)
free_lifo_memory();
else
mmap_fclose(thefile);
return;
}
nagios/cgi/outages.c 0000664 0000000 0000000 00000050202 12210155146 0014707 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* OUTAGES.C - Nagios Network Outages CGI
*
* Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 01-08-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.
*************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/comments.h"
#include "../include/statusdata.h"
#include "../include/cgiutils.h"
#include "../include/getcgi.h"
#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;
extern char main_config_file[MAX_FILENAME_LENGTH];
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 */
typedef struct hostoutage_struct {
host *hst;
int severity;
int affected_child_hosts;
int affected_child_services;
unsigned long monitored_time;
unsigned long time_up;
float percent_time_up;
unsigned long time_down;
float percent_time_down;
unsigned long time_unreachable;
float percent_time_unreachable;
struct hostoutage_struct *next;
} hostoutage;
/* HOSTOUTAGESORT structure */
typedef struct hostoutagesort_struct {
hostoutage *outage;
struct hostoutagesort_struct *next;
} hostoutagesort;
void document_header(int);
void document_footer(void);
int process_cgivars(void);
void display_network_outages(void);
void find_hosts_causing_outages(void);
void calculate_outage_effects(void);
void calculate_outage_effect_of_host(host *, int *, int *);
int is_route_to_host_blocked(host *);
int number_of_host_services(host *);
void add_hostoutage(host *);
void sort_hostoutages(void);
void free_hostoutage_list(void);
void free_hostoutagesort_list(void);
authdata current_authdata;
hostoutage *hostoutage_list = NULL;
hostoutagesort *hostoutagesort_list = NULL;
int service_severity_divisor = 4; /* default = services are 1/4 as important as hosts */
int embedded = FALSE;
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;
}
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_authdata);
if(display_header == TRUE) {
/* begin top table */
printf("
\n");
/* display context-sensitive help */
display_context_help(CONTEXTHELP_OUTAGES);
printf("
\n");
/* end of top table */
printf("
\n");
printf("
\n");
}
/* display network outage info */
display_network_outages();
document_footer();
/* free memory allocated to comment data */
free_comment_data();
/* free all allocated memory */
free_memory();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
time_t expire_time;
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
printf("Refresh: %d\r\n", refresh_rate);
time(¤t_time);
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: text/html\r\n\r\n");
if(embedded == TRUE)
return;
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("Network Outages\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("", url_stylesheets_path, COMMON_CSS);
printf("", url_stylesheets_path, OUTAGES_CSS);
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(OUTAGES_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(OUTAGES_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
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) {
x++;
continue;
}
/* we found the service severity divisor option */
if(!strcmp(variables[x], "service_divisor")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
service_severity_divisor = atoi(variables[x]);
if(service_severity_divisor < 1)
service_severity_divisor = 1;
}
/* we found the embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
/* we found the noheader option */
else if(!strcmp(variables[x], "noheader"))
display_header = FALSE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
/* shows all hosts that are causing network outages */
void display_network_outages(void) {
char temp_buffer[MAX_INPUT_BUFFER];
int number_of_problem_hosts = 0;
int number_of_blocking_problem_hosts = 0;
hostoutagesort *temp_hostoutagesort;
hostoutage *temp_hostoutage;
hoststatus *temp_hoststatus;
int odd = 0;
char *bg_class = "";
char *status = "";
int days;
int hours;
int minutes;
int seconds;
int total_comments;
time_t t;
time_t current_time;
char state_duration[48];
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");
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");
return;
}
/* find all hosts that are causing network outages */
find_hosts_causing_outages();
/* calculate outage effects */
calculate_outage_effects();
/* sort the outage list by severity */
sort_hostoutages();
/* count the number of top-level hosts that are down and the ones that are actually blocking children hosts */
for(temp_hostoutage = hostoutage_list; temp_hostoutage != NULL; temp_hostoutage = temp_hostoutage->next) {
number_of_problem_hosts++;
if(temp_hostoutage->affected_child_hosts > 1)
number_of_blocking_problem_hosts++;
}
/* display the problem hosts... */
printf("
\n", total_entries);
/* free memory allocated to the host outage list */
free_hostoutage_list();
free_hostoutagesort_list();
return;
}
/* determine what hosts are causing network outages */
void find_hosts_causing_outages(void) {
hoststatus *temp_hoststatus;
host *temp_host;
/* check all hosts */
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) {
/* find the host entry */
temp_host = find_host(temp_hoststatus->host_name);
if(temp_host == NULL)
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);
}
}
return;
}
/* adds a host outage entry */
void add_hostoutage(host *hst) {
hostoutage *new_hostoutage;
/* allocate memory for a new structure */
new_hostoutage = (hostoutage *)malloc(sizeof(hostoutage));
if(new_hostoutage == NULL)
return;
new_hostoutage->hst = hst;
new_hostoutage->severity = 0;
new_hostoutage->affected_child_hosts = 0;
new_hostoutage->affected_child_services = 0;
/* add the structure to the head of the list in memory */
new_hostoutage->next = hostoutage_list;
hostoutage_list = new_hostoutage;
return;
}
/* frees all memory allocated to the host outage list */
void free_hostoutage_list(void) {
hostoutage *this_hostoutage;
hostoutage *next_hostoutage;
/* free all list members */
for(this_hostoutage = hostoutage_list; this_hostoutage != NULL; this_hostoutage = next_hostoutage) {
next_hostoutage = this_hostoutage->next;
free(this_hostoutage);
}
/* reset list pointer */
hostoutage_list = NULL;
return;
}
/* frees all memory allocated to the host outage sort list */
void free_hostoutagesort_list(void) {
hostoutagesort *this_hostoutagesort;
hostoutagesort *next_hostoutagesort;
/* free all list members */
for(this_hostoutagesort = hostoutagesort_list; this_hostoutagesort != NULL; this_hostoutagesort = next_hostoutagesort) {
next_hostoutagesort = this_hostoutagesort->next;
free(this_hostoutagesort);
}
/* reset list pointer */
hostoutagesort_list = NULL;
return;
}
/* calculates network outage effect of all hosts that are causing blockages */
void calculate_outage_effects(void) {
hostoutage *temp_hostoutage;
/* check all hosts causing problems */
for(temp_hostoutage = hostoutage_list; temp_hostoutage != NULL; temp_hostoutage = temp_hostoutage->next) {
/* calculate the outage effect of this particular hosts */
calculate_outage_effect_of_host(temp_hostoutage->hst, &temp_hostoutage->affected_child_hosts, &temp_hostoutage->affected_child_services);
temp_hostoutage->severity = (temp_hostoutage->affected_child_hosts + (temp_hostoutage->affected_child_services / service_severity_divisor));
}
return;
}
/* calculates network outage effect of a particular host being down or unreachable */
void calculate_outage_effect_of_host(host *hst, int *affected_hosts, int *affected_services) {
int total_child_hosts_affected = 0;
int total_child_services_affected = 0;
int temp_child_hosts_affected = 0;
int temp_child_services_affected = 0;
host *temp_host;
/* find all child hosts of this host */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
/* skip this host if it is not a child */
if(is_host_immediate_child_of_host(hst, temp_host) == FALSE)
continue;
/* calculate the outage effect of the child */
calculate_outage_effect_of_host(temp_host, &temp_child_hosts_affected, &temp_child_services_affected);
/* keep a running total of outage effects */
total_child_hosts_affected += temp_child_hosts_affected;
total_child_services_affected += temp_child_services_affected;
}
*affected_hosts = total_child_hosts_affected + 1;
*affected_services = total_child_services_affected + number_of_host_services(hst);
return;
}
/* tests whether or not a host is "blocked" by upstream parents (host is already assumed to be down or unreachable) */
int is_route_to_host_blocked(host *hst) {
hostsmember *temp_hostsmember;
hoststatus *temp_hoststatus;
/* if the host has no parents, it is not being blocked by anyone */
if(hst->parent_hosts == NULL)
return FALSE;
/* check all parent hosts */
for(temp_hostsmember = hst->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
/* find the parent host's status */
temp_hoststatus = find_hoststatus(temp_hostsmember->host_name);
if(temp_hoststatus == NULL)
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)
return FALSE;
}
return TRUE;
}
/* calculates the number of services associated a particular host */
int number_of_host_services(host *hst) {
int total_services = 0;
service *temp_service;
/* check all services */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
if(!strcmp(temp_service->host_name, hst->name))
total_services++;
}
return total_services;
}
/* sort the host outages by severity */
void sort_hostoutages(void) {
hostoutagesort *last_hostoutagesort;
hostoutagesort *new_hostoutagesort;
hostoutagesort *temp_hostoutagesort;
hostoutage *temp_hostoutage;
if(hostoutage_list == NULL)
return;
/* sort all host outage entries */
for(temp_hostoutage = hostoutage_list; temp_hostoutage != NULL; temp_hostoutage = temp_hostoutage->next) {
/* allocate memory for a new sort structure */
new_hostoutagesort = (hostoutagesort *)malloc(sizeof(hostoutagesort));
if(new_hostoutagesort == NULL)
return;
new_hostoutagesort->outage = temp_hostoutage;
last_hostoutagesort = hostoutagesort_list;
for(temp_hostoutagesort = hostoutagesort_list; temp_hostoutagesort != NULL; temp_hostoutagesort = temp_hostoutagesort->next) {
if(new_hostoutagesort->outage->severity >= temp_hostoutagesort->outage->severity) {
new_hostoutagesort->next = temp_hostoutagesort;
if(temp_hostoutagesort == hostoutagesort_list)
hostoutagesort_list = new_hostoutagesort;
else
last_hostoutagesort->next = new_hostoutagesort;
break;
}
else
last_hostoutagesort = temp_hostoutagesort;
}
if(hostoutagesort_list == NULL) {
new_hostoutagesort->next = NULL;
hostoutagesort_list = new_hostoutagesort;
}
else if(temp_hostoutagesort == NULL) {
new_hostoutagesort->next = NULL;
last_hostoutagesort->next = new_hostoutagesort;
}
}
return;
}
nagios/cgi/showlog.c 0000664 0000000 0000000 00000040224 12210155146 0014725 0 ustar 00root root 0000000 0000000 /***********************************************************************
*
* 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.
*
* 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/getcgi.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
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_stylesheets_path[MAX_FILENAME_LENGTH];
extern int log_rotation_method;
extern int enable_splunk_integration;
void document_header(int);
void document_footer(void);
int process_cgivars(void);
authdata current_authdata;
int display_log(void);
char log_file_to_use[MAX_FILENAME_LENGTH] = "";
int log_archive = 0;
int use_lifo = TRUE;
int embedded = FALSE;
int display_header = TRUE;
int display_frills = TRUE;
int display_timebreaks = TRUE;
int main(void) {
int result = OK;
char temp_buffer[MAX_INPUT_BUFFER];
/* get the CGI variables 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;
}
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_authdata);
/* determine what log file we should be using */
get_log_archive_to_use(log_archive, log_file_to_use, (int)sizeof(log_file_to_use));
if(display_header == TRUE) {
/* begin top table */
printf("
\n");
printf("
\n");
/* left column of top table - info box */
printf("
\n");
printf("\n");
}
/* display the contents of the log file */
display_log();
document_footer();
/* free allocated memory */
free_memory();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
time_t expire_time;
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
time(¤t_time);
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: text/html\r\n\r\n");
if(embedded == TRUE)
return;
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("Nagios Log File\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("\n", url_stylesheets_path, COMMON_CSS);
printf("\n", url_stylesheets_path, SHOWLOG_CSS);
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(SHOWLOG_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(SHOWLOG_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
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 archive argument */
else if(!strcmp(variables[x], "archive")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
log_archive = atoi(variables[x]);
if(log_archive < 0)
log_archive = 0;
}
/* we found the order argument */
else if(!strcmp(variables[x], "oldestfirst")) {
use_lifo = FALSE;
}
/* we found the embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
/* we found the noheader option */
else if(!strcmp(variables[x], "noheader"))
display_header = FALSE;
/* we found the nofrills option */
else if(!strcmp(variables[x], "nofrills"))
display_frills = FALSE;
/* we found the notimebreaks option */
else if(!strcmp(variables[x], "notimebreaks"))
display_timebreaks = FALSE;
/* we received an invalid argument */
else
error = TRUE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
/* display the contents of the log file */
int display_log(void) {
char *input = NULL;
char image[MAX_INPUT_BUFFER];
char image_alt[MAX_INPUT_BUFFER];
time_t t;
char *temp_buffer = NULL;
char date_time[MAX_DATETIME_LENGTH];
int error = FALSE;
mmapfile *thefile = NULL;
char last_message_date[MAX_INPUT_BUFFER] = "";
char current_message_date[MAX_INPUT_BUFFER] = "";
struct tm *time_ptr = NULL;
/* check to see if the user is authorized to view the log file */
if(is_authorized_for_system_information(¤t_authdata) == FALSE) {
printf("\n");
printf("
It appears as though you do not have permission to view the log file...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI and check the authorization options in your CGI configuration file.
\n");
if(display_type == DISPLAY_HOSTS) {
printf("View History For %s \n", HISTORY_CGI, (show_all_hosts == TRUE) ? "all" : url_encode(host_name), (show_all_hosts == TRUE) ? "all hosts" : "This Host");
printf("View Notifications For %s\n", NOTIFICATIONS_CGI, (show_all_hosts == TRUE) ? "all" : url_encode(host_name), (show_all_hosts == TRUE) ? "All Hosts" : "This Host");
if(show_all_hosts == FALSE)
printf(" View Service Status Detail For All Hosts\n", STATUS_CGI);
else
printf(" View Host Status Detail For All Hosts\n", STATUS_CGI);
}
else if(display_type == DISPLAY_SERVICEGROUPS) {
if(show_all_servicegroups == FALSE) {
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_GRID || group_style_type == STYLE_SUMMARY)
printf("View Service Status Detail For This Service Group \n", STATUS_CGI, url_encode(servicegroup_name));
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_GRID || group_style_type == STYLE_SUMMARY)
printf("View Status Overview For This Service Group \n", STATUS_CGI, url_encode(servicegroup_name));
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_GRID)
printf("View Status Summary For This Service Group \n", STATUS_CGI, url_encode(servicegroup_name));
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_SUMMARY)
printf("View Service Status Grid For This Service Group \n", STATUS_CGI, url_encode(servicegroup_name));
if(group_style_type == STYLE_DETAIL)
printf("View Service Status Detail For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW)
printf("View Status Overview For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_SUMMARY)
printf("View Status Summary For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_GRID)
printf("View Service Status Grid For All Service Groups \n", STATUS_CGI);
}
else {
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_GRID || group_style_type == STYLE_SUMMARY)
printf("View Service Status Detail For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_GRID || group_style_type == STYLE_SUMMARY)
printf("View Status Overview For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_GRID)
printf("View Status Summary For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_SUMMARY)
printf("View Service Status Grid For All Service Groups \n", STATUS_CGI);
}
}
else {
if(show_all_hostgroups == FALSE) {
if(group_style_type == STYLE_DETAIL)
printf("View Service Status Detail For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_HOST_DETAIL)
printf("View Host Status Detail For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW)
printf("View Status Overview For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_SUMMARY)
printf("View Status Summary For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_GRID)
printf("View Status Grid For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Service Status Detail For This Host Group \n", STATUS_CGI, url_encode(hostgroup_name));
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID)
printf("View Host Status Detail For This Host Group \n", STATUS_CGI, url_encode(hostgroup_name));
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Overview For This Host Group \n", STATUS_CGI, url_encode(hostgroup_name));
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Summary For This Host Group \n", STATUS_CGI, url_encode(hostgroup_name));
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Grid For This Host Group \n", STATUS_CGI, url_encode(hostgroup_name));
}
else {
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Service Status Detail For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID)
printf("View Host Status Detail For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Overview For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Summary For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Grid For All Host Groups \n", STATUS_CGI);
}
}
printf("
\n");
printf("
\n");
printf("
\n");
/* middle column of top row */
printf("
\n");
show_host_status_totals();
printf("
\n");
/* right hand column of top row */
printf("
\n");
show_service_status_totals();
printf("
\n");
/* display context-sensitive help */
printf("
", EXTINFO_CGI, DISPLAY_HOST_INFO, url_encode(temp_status->host_name), url_images_path, ACKNOWLEDGEMENT_ICON, STATUS_ICON_WIDTH, STATUS_ICON_HEIGHT);
}
/* only show comments if this is a non-read-only user */
if(is_authorized_for_read_only(¤t_authdata) == FALSE) {
if(total_comments > 0)
printf("
\n");
total_comments = number_of_service_comments(temp_service->host_name, temp_service->description);
/* only show comments if this is a non-read-only user */
if(is_authorized_for_read_only(¤t_authdata) == FALSE) {
if(total_comments > 0) {
printf("
\n");
/* mod to account for paging */
if(visible_entries != 0)
last_host = temp_status->host_name;
}
}
printf("
\n");
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE) {
if(servicestatus_list != NULL) {
printf("
It appears as though you do not have permission to view information for any of the services 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 service 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");
}
}
else {
/* do page numbers if applicable */
create_pagenumbers(total_entries, visible_entries, temp_url, TRUE);
}
return;
}
/* display a detailed listing of the status of all hosts... */
void show_host_detail(void) {
time_t t;
char date_time[MAX_DATETIME_LENGTH];
char state_duration[48];
char status[MAX_INPUT_BUFFER];
char temp_buffer[MAX_INPUT_BUFFER];
char temp_url[MAX_INPUT_BUFFER];
char *processed_string = NULL;
char *status_class = "";
char *status_bg_class = "";
hoststatus *temp_status = NULL;
hostgroup *temp_hostgroup = NULL;
host *temp_host = NULL;
hostsort *temp_hostsort = NULL;
int odd = 0;
int total_comments = 0;
int user_has_seen_something = FALSE;
int use_sort = FALSE;
int result = OK;
int first_entry = TRUE;
int days;
int hours;
int minutes;
int seconds;
int duration_error = FALSE;
int total_entries = 0;
int visible_entries = 0;
// int show_host = FALSE;
/* sort the host list if necessary */
if(sort_type != SORT_NONE) {
result = sort_hosts(sort_type, sort_option);
if(result == ERROR)
use_sort = FALSE;
else
use_sort = TRUE;
}
else
use_sort = FALSE;
// printf("
\n");
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE) {
if(hoststatus_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");
}
}
else {
/* do page numbers if applicable */
create_pagenumbers(total_entries, visible_entries, temp_url, FALSE);
}
return;
}
/* show an overview of servicegroup(s)... */
void show_servicegroup_overviews(void) {
servicegroup *temp_servicegroup = NULL;
int current_column;
int user_has_seen_something = FALSE;
int servicegroup_error = FALSE;
//printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Service Overview For ");
if(show_all_servicegroups == TRUE)
printf("All Service Groups");
else
printf("Service Group '%s'", servicegroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
//printf("\n");
/* display status overviews for all servicegroups */
if(show_all_servicegroups == TRUE) {
printf("
\n");
printf("
\n");
current_column = 1;
/* loop through all servicegroups... */
for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next) {
/* make sure the user is authorized to view at least one host in this servicegroup */
if(is_authorized_for_servicegroup(temp_servicegroup, ¤t_authdata) == FALSE)
continue;
if(current_column == 1)
printf("
Sorry, but service group '%s' doesn't seem to exist...
", servicegroup_name);
servicegroup_error = TRUE;
}
}
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && servicegroup_error == FALSE) {
//printf("
\n");
printf("
\n");
if(servicegroup_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 are no service groups defined.
\n");
}
printf("
\n");
//printf("\n");
}
return;
}
/* shows an overview of a specific servicegroup... */
void show_servicegroup_overview(servicegroup *temp_servicegroup) {
servicesmember *temp_member;
host *temp_host;
host *last_host;
hoststatus *temp_hoststatus = NULL;
int odd = 0;
printf("
\n");
/* find all hosts that have services that are members of the servicegroup */
last_host = NULL;
for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) {
/* find the host */
temp_host = find_host(temp_member->host_name);
if(temp_host == NULL)
continue;
/* skip this if it isn't a new host... */
if(temp_host == last_host)
continue;
/* find the host status */
temp_hoststatus = find_hoststatus(temp_host->name);
if(temp_hoststatus == NULL)
continue;
/* make sure we only display hosts of the specified status levels */
if(!(host_status_types & temp_hoststatus->status))
continue;
/* make sure we only display hosts that have the desired properties */
if(passes_host_properties_filter(temp_hoststatus) == FALSE)
continue;
if(odd)
odd = 0;
else
odd = 1;
show_servicegroup_hostgroup_member_overview(temp_hoststatus, odd, temp_servicegroup);
last_host = temp_host;
}
printf("
\n");
printf("
\n");
return;
}
/* show a summary of servicegroup(s)... */
void show_servicegroup_summaries(void) {
servicegroup *temp_servicegroup = NULL;
int user_has_seen_something = FALSE;
int servicegroup_error = FALSE;
int odd = 0;
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Status Summary For ");
if(show_all_servicegroups == TRUE)
printf("All Service Groups");
else
printf("Service Group '%s'", servicegroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Service Group
Host Status Summary
Service Status Summary
\n");
printf("
\n");
/* display status summary for all servicegroups */
if(show_all_servicegroups == TRUE) {
/* loop through all servicegroups... */
for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next) {
/* make sure the user is authorized to view at least one host in this servicegroup */
if(is_authorized_for_servicegroup(temp_servicegroup, ¤t_authdata) == FALSE)
continue;
if(odd == 0)
odd = 1;
else
odd = 0;
/* show summary for this servicegroup */
show_servicegroup_summary(temp_servicegroup, odd);
user_has_seen_something = TRUE;
}
}
/* else just show summary for a specific servicegroup */
else {
temp_servicegroup = find_servicegroup(servicegroup_name);
if(temp_servicegroup == NULL)
servicegroup_error = TRUE;
else {
show_servicegroup_summary(temp_servicegroup, 1);
user_has_seen_something = TRUE;
}
}
printf("
\n");
printf("
\n");
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && servicegroup_error == FALSE) {
printf("
\n");
if(servicegroup_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 are no service groups defined.
\n");
}
printf("
\n");
}
/* we couldn't find the servicegroup */
else if(servicegroup_error == TRUE) {
printf("
\n");
printf("
Sorry, but servicegroup '%s' doesn't seem to exist...
\n", servicegroup_name);
printf("
\n");
}
return;
}
/* displays status summary information for a specific servicegroup */
void show_servicegroup_summary(servicegroup *temp_servicegroup, int odd) {
char *status_bg_class = "";
if(odd == 1)
status_bg_class = "Even";
else
status_bg_class = "Odd";
printf("
\n");
if((services_ok + services_warning + services_unknown + services_critical + services_pending) == 0)
printf("No matching services");
return;
}
/* show a grid layout of servicegroup(s)... */
void show_servicegroup_grids(void) {
servicegroup *temp_servicegroup = NULL;
int user_has_seen_something = FALSE;
int servicegroup_error = FALSE;
int odd = 0;
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Status Grid For ");
if(show_all_servicegroups == TRUE)
printf("All Service Groups");
else
printf("Service Group '%s'", servicegroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
/* display status grids for all servicegroups */
if(show_all_servicegroups == TRUE) {
/* loop through all servicegroups... */
for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next) {
/* make sure the user is authorized to view at least one host in this servicegroup */
if(is_authorized_for_servicegroup(temp_servicegroup, ¤t_authdata) == FALSE)
continue;
if(odd == 0)
odd = 1;
else
odd = 0;
/* show grid for this servicegroup */
show_servicegroup_grid(temp_servicegroup);
user_has_seen_something = TRUE;
}
}
/* else just show grid for a specific servicegroup */
else {
temp_servicegroup = find_servicegroup(servicegroup_name);
if(temp_servicegroup == NULL)
servicegroup_error = TRUE;
else {
show_servicegroup_grid(temp_servicegroup);
user_has_seen_something = TRUE;
}
}
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && servicegroup_error == FALSE) {
printf("
\n");
if(servicegroup_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 are no service groups defined.
\n");
}
printf("
\n");
}
/* we couldn't find the servicegroup */
else if(servicegroup_error == TRUE) {
printf("
\n");
printf("
Sorry, but servicegroup '%s' doesn't seem to exist...
\n", servicegroup_name);
printf("
\n");
}
return;
}
/* 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 = "";
char *processed_string = NULL;
servicesmember *temp_member;
servicesmember *temp_member2;
host *temp_host;
host *last_host;
hoststatus *temp_hoststatus;
servicestatus *temp_servicestatus;
int odd = 0;
int current_item;
printf("
\n");
/* find all hosts that have services that are members of the servicegroup */
last_host = NULL;
for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) {
/* find the host */
temp_host = find_host(temp_member->host_name);
if(temp_host == NULL)
continue;
/* get the status of the host */
temp_hoststatus = find_hoststatus(temp_host->name);
if(temp_hoststatus == NULL)
continue;
/* skip this if it isn't a new host... */
if(temp_host == last_host)
continue;
if(odd == 1) {
status_bg_class = "Even";
odd = 0;
}
else {
status_bg_class = "Odd";
odd = 1;
}
printf("
\n");
printf("\n");
return;
}
/* show an overview of hostgroup(s)... */
void show_hostgroup_overviews(void) {
hostgroup *temp_hostgroup = NULL;
int current_column;
int user_has_seen_something = FALSE;
int hostgroup_error = FALSE;
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Service Overview For ");
if(show_all_hostgroups == TRUE)
printf("All Host Groups");
else
printf("Host Group '%s'", hostgroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
/* display status overviews for all hostgroups */
if(show_all_hostgroups == TRUE) {
printf("
\n");
printf("
\n");
current_column = 1;
/* loop through all hostgroups... */
for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next) {
/* make sure the user is authorized to view this hostgroup */
if(is_authorized_for_hostgroup(temp_hostgroup, ¤t_authdata) == FALSE)
continue;
if(current_column == 1)
printf("
Sorry, but host group '%s' doesn't seem to exist...
", hostgroup_name);
hostgroup_error = TRUE;
}
}
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && hostgroup_error == FALSE) {
printf("
\n");
printf("
\n");
if(hoststatus_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("
\n");
printf("\n");
}
return;
}
/* shows an overview of a specific hostgroup... */
void show_hostgroup_overview(hostgroup *hstgrp) {
hostsmember *temp_member = NULL;
host *temp_host = NULL;
hoststatus *temp_hoststatus = NULL;
int odd = 0;
/* make sure the user is authorized to view this hostgroup */
if(is_authorized_for_hostgroup(hstgrp, ¤t_authdata) == FALSE)
return;
printf("
\n");
/* find all the hosts that belong to the hostgroup */
for(temp_member = hstgrp->members; temp_member != NULL; temp_member = temp_member->next) {
/* find the host... */
temp_host = find_host(temp_member->host_name);
if(temp_host == NULL)
continue;
/* find the host status */
temp_hoststatus = find_hoststatus(temp_host->name);
if(temp_hoststatus == NULL)
continue;
/* make sure we only display hosts of the specified status levels */
if(!(host_status_types & temp_hoststatus->status))
continue;
/* make sure we only display hosts that have the desired properties */
if(passes_host_properties_filter(temp_hoststatus) == FALSE)
continue;
if(odd)
odd = 0;
else
odd = 1;
show_servicegroup_hostgroup_member_overview(temp_hoststatus, odd, NULL);
}
printf("
\n");
if((total_ok + total_warning + total_unknown + total_critical + total_pending) == 0)
printf("No matching services");
return;
}
/* show a summary of hostgroup(s)... */
void show_hostgroup_summaries(void) {
hostgroup *temp_hostgroup = NULL;
int user_has_seen_something = FALSE;
int hostgroup_error = FALSE;
int odd = 0;
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Status Summary For ");
if(show_all_hostgroups == TRUE)
printf("All Host Groups");
else
printf("Host Group '%s'", hostgroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Host Group
Host Status Summary
Service Status Summary
\n");
printf("
\n");
/* display status summary for all hostgroups */
if(show_all_hostgroups == TRUE) {
/* loop through all hostgroups... */
for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next) {
/* make sure the user is authorized to view this hostgroup */
if(is_authorized_for_hostgroup(temp_hostgroup, ¤t_authdata) == FALSE)
continue;
if(odd == 0)
odd = 1;
else
odd = 0;
/* show summary for this hostgroup */
show_hostgroup_summary(temp_hostgroup, odd);
user_has_seen_something = TRUE;
}
}
/* else just show summary for a specific hostgroup */
else {
temp_hostgroup = find_hostgroup(hostgroup_name);
if(temp_hostgroup == NULL)
hostgroup_error = TRUE;
else {
show_hostgroup_summary(temp_hostgroup, 1);
user_has_seen_something = TRUE;
}
}
printf("
\n");
printf("
\n");
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && hostgroup_error == FALSE) {
printf("
\n");
if(hoststatus_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("
\n");
}
/* we couldn't find the hostgroup */
else if(hostgroup_error == TRUE) {
printf("
\n");
printf("
Sorry, but hostgroup '%s' doesn't seem to exist...
\n", hostgroup_name);
printf("
\n");
}
return;
}
/* displays status summary information for a specific hostgroup */
void show_hostgroup_summary(hostgroup *temp_hostgroup, int odd) {
char *status_bg_class = "";
if(odd == 1)
status_bg_class = "Even";
else
status_bg_class = "Odd";
printf("
\n");
if((services_ok + services_warning + services_unknown + services_critical + services_pending) == 0)
printf("No matching services");
return;
}
/* show a grid layout of hostgroup(s)... */
void show_hostgroup_grids(void) {
hostgroup *temp_hostgroup = NULL;
int user_has_seen_something = FALSE;
int hostgroup_error = FALSE;
int odd = 0;
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Status Grid For ");
if(show_all_hostgroups == TRUE)
printf("All Host Groups");
else
printf("Host Group '%s'", hostgroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
/* display status grids for all hostgroups */
if(show_all_hostgroups == TRUE) {
/* loop through all hostgroups... */
for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next) {
/* make sure the user is authorized to view this hostgroup */
if(is_authorized_for_hostgroup(temp_hostgroup, ¤t_authdata) == FALSE)
continue;
if(odd == 0)
odd = 1;
else
odd = 0;
/* show grid for this hostgroup */
show_hostgroup_grid(temp_hostgroup);
user_has_seen_something = TRUE;
}
}
/* else just show grid for a specific hostgroup */
else {
temp_hostgroup = find_hostgroup(hostgroup_name);
if(temp_hostgroup == NULL)
hostgroup_error = TRUE;
else {
show_hostgroup_grid(temp_hostgroup);
user_has_seen_something = TRUE;
}
}
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && hostgroup_error == FALSE) {
printf("
\n");
if(hoststatus_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("
\n");
}
/* we couldn't find the hostgroup */
else if(hostgroup_error == TRUE) {
printf("
\n");
printf("
Sorry, but hostgroup '%s' doesn't seem to exist...
\n", hostgroup_name);
printf("
\n");
}
return;
}
/* 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 = "";
host *temp_host;
service *temp_service;
hoststatus *temp_hoststatus;
servicestatus *temp_servicestatus;
char *processed_string = NULL;
int odd = 0;
int current_item;
printf("
");
printf(" Services: ");
service_totals = get_servicestatus_count(hst->name, SERVICE_OK);
if(service_totals > 0)
printf("- %d ok ", service_totals);
service_totals = get_servicestatus_count(hst->name, SERVICE_CRITICAL);
if(service_totals > 0)
printf("- %d critical ", service_totals);
service_totals = get_servicestatus_count(hst->name, SERVICE_WARNING);
if(service_totals > 0)
printf("- %d warning ", service_totals);
service_totals = get_servicestatus_count(hst->name, SERVICE_UNKNOWN);
if(service_totals > 0)
printf("- %d unknown ", service_totals);
service_totals = get_servicestatus_count(hst->name, SERVICE_PENDING);
if(service_totals > 0)
printf("- %d pending ", service_totals);
return;
}
/* draws a solid line */
void draw_line(int x1, int y1, int x2, int y2, int color) {
if(create_type == CREATE_HTML)
return;
gdImageLine(map_image, x1, y1, x2, y2, color);
return;
}
/* draws a dotted line */
void draw_dotted_line(int x1, int y1, int x2, int y2, int color) {
int styleDotted[12];
styleDotted[0] = color;
styleDotted[1] = gdTransparent;
styleDotted[2] = gdTransparent;
styleDotted[3] = gdTransparent;
styleDotted[4] = gdTransparent;
styleDotted[5] = gdTransparent;
styleDotted[6] = color;
styleDotted[7] = gdTransparent;
styleDotted[8] = gdTransparent;
styleDotted[9] = gdTransparent;
styleDotted[10] = gdTransparent;
styleDotted[11] = gdTransparent;
/* sets current style to a dashed line */
gdImageSetStyle(map_image, styleDotted, 12);
/* draws a line (dotted) */
gdImageLine(map_image, x1, y1, x2, y2, gdStyled);
return;
}
/* draws a dashed line */
void draw_dashed_line(int x1, int y1, int x2, int y2, int color) {
int styleDashed[12];
styleDashed[0] = color;
styleDashed[1] = color;
styleDashed[2] = color;
styleDashed[3] = color;
styleDashed[4] = gdTransparent;
styleDashed[5] = gdTransparent;
styleDashed[6] = color;
styleDashed[7] = color;
styleDashed[8] = color;
styleDashed[9] = color;
styleDashed[10] = gdTransparent;
styleDashed[11] = gdTransparent;
/* sets current style to a dashed line */
gdImageSetStyle(map_image, styleDashed, 12);
/* draws a line (dashed) */
gdImageLine(map_image, x1, y1, x2, y2, gdStyled);
return;
}
/******************************************************************/
/*********************** GRAPHICS FUNCTIONS ***********************/
/******************************************************************/
/* initialize graphics */
int initialize_graphics(void) {
char image_input_file[MAX_INPUT_BUFFER];
if(create_type == CREATE_HTML)
return ERROR;
/* allocate buffer for storing image */
#ifndef HAVE_GDIMAGECREATETRUECOLOR
map_image = gdImageCreate(canvas_width, canvas_height);
#else
map_image = gdImageCreateTrueColor(canvas_width, canvas_height);
#endif
if(map_image == NULL)
return ERROR;
/* allocate colors used for drawing */
color_white = gdImageColorAllocate(map_image, 255, 255, 255);
color_black = gdImageColorAllocate(map_image, 0, 0, 0);
color_grey = gdImageColorAllocate(map_image, 128, 128, 128);
color_lightgrey = gdImageColorAllocate(map_image, 210, 210, 210);
color_red = gdImageColorAllocate(map_image, 255, 0, 0);
color_lightred = gdImageColorAllocate(map_image, 215, 175, 175);
color_green = gdImageColorAllocate(map_image, 0, 175, 0);
color_lightgreen = gdImageColorAllocate(map_image, 210, 255, 215);
color_blue = gdImageColorAllocate(map_image, 0, 0, 255);
color_yellow = gdImageColorAllocate(map_image, 255, 255, 0);
color_orange = gdImageColorAllocate(map_image, 255, 100, 25);
color_transparency_index = gdImageColorAllocate(map_image, color_transparency_index_r, color_transparency_index_g, color_transparency_index_b);
/* set transparency index */
#ifndef HAVE_GDIMAGECREATETRUECOLOR
gdImageColorTransparent(map_image, color_white);
#else
gdImageColorTransparent(map_image, color_transparency_index);
/* set background */
gdImageFill(map_image, 0, 0, color_transparency_index);
#endif
/* make sure the graphic is interlaced */
gdImageInterlace(map_image, 1);
/* get the path where we will be reading logo images from (GD2 format)... */
snprintf(physical_logo_images_path, sizeof(physical_logo_images_path) - 1, "%slogos/", physical_images_path);
physical_logo_images_path[sizeof(physical_logo_images_path) - 1] = '\x0';
/* load the unknown icon to use for hosts that don't have pretty images associated with them... */
snprintf(image_input_file, sizeof(image_input_file) - 1, "%s%s", physical_logo_images_path, UNKNOWN_GD2_ICON);
image_input_file[sizeof(image_input_file) - 1] = '\x0';
unknown_logo_image = load_image_from_file(image_input_file);
return OK;
}
/* loads a graphic image (GD2, JPG or PNG) from file into memory */
gdImagePtr load_image_from_file(char *filename) {
FILE *fp;
gdImagePtr im = NULL;
char *ext;
/* make sure we were passed a file name */
if(filename == NULL)
return NULL;
/* find the file extension */
if((ext = rindex(filename, '.')) == NULL)
return NULL;
/* open the file for reading (binary mode) */
fp = fopen(filename, "rb");
if(fp == NULL)
return NULL;
/* attempt to read files in various formats */
if(!strcasecmp(ext, ".png"))
im = gdImageCreateFromPng(fp);
else if(!strcasecmp(ext, ".jpg") || !strcasecmp(ext, ".jpeg"))
im = gdImageCreateFromJpeg(fp);
else if(!strcasecmp(ext, ".xbm"))
im = gdImageCreateFromXbm(fp);
else if(!strcasecmp(ext, ".gd2"))
im = gdImageCreateFromGd2(fp);
else if(!strcasecmp(ext, ".gd"))
im = gdImageCreateFromGd(fp);
/* fall back to GD2 image format */
else
im = gdImageCreateFromGd2(fp);
/* close the file */
fclose(fp);
return im;
}
/* draw graphics */
void write_graphics(void) {
FILE *image_output_file = NULL;
if(create_type == CREATE_HTML)
return;
/* use STDOUT for writing the image data... */
image_output_file = stdout;
/* write the image out in PNG format */
gdImagePng(map_image, image_output_file);
/* or we could write the image out in JPG format... */
/*gdImageJpeg(map_image,image_output_file,99);*/
return;
}
/* cleanup graphics resources */
void cleanup_graphics(void) {
if(create_type == CREATE_HTML)
return;
/* free memory allocated to image */
gdImageDestroy(map_image);
return;
}
/******************************************************************/
/************************* MISC FUNCTIONS *************************/
/******************************************************************/
/* write JavaScript code an layer for popup window */
void write_popup_code(void) {
char *border_color = "#000000";
char *background_color = "#ffffcc";
int border = 1;
int padding = 3;
int x_offset = 3;
int y_offset = 3;
printf("\n");
return;
}
/* adds a layer to the list in memory */
int add_layer(char *group_name) {
layer *new_layer;
if(group_name == NULL)
return ERROR;
/* allocate memory for a new layer */
new_layer = (layer *)malloc(sizeof(layer));
if(new_layer == NULL)
return ERROR;
new_layer->layer_name = (char *)malloc(strlen(group_name) + 1);
if(new_layer->layer_name == NULL) {
free(new_layer);
return ERROR;
}
strcpy(new_layer->layer_name, group_name);
/* add new layer to head of layer list */
new_layer->next = layer_list;
layer_list = new_layer;
return OK;
}
/* frees memory allocated to the layer list */
void free_layer_list(void) {
layer *this_layer;
layer *next_layer;
return;
for(this_layer = layer_list; layer_list != NULL; this_layer = next_layer) {
next_layer = this_layer->next;
free(this_layer->layer_name);
free(this_layer);
}
return;
}
/* 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;
if(hst == NULL)
return FALSE;
/* check each layer... */
for(temp_layer = layer_list; temp_layer != NULL; temp_layer = temp_layer->next) {
/* find the hostgroup */
temp_hostgroup = find_hostgroup(temp_layer->layer_name);
if(temp_hostgroup == NULL)
continue;
/* is the requested host a member of the hostgroup/layer? */
if(is_host_member_of_hostgroup(temp_hostgroup, hst) == TRUE)
return TRUE;
}
return FALSE;
}
/* print layer url info */
void print_layer_url(int get_method) {
layer *temp_layer;
for(temp_layer = layer_list; temp_layer != NULL; temp_layer = temp_layer->next) {
if(get_method == TRUE)
printf("&layer=%s", escape_string(temp_layer->layer_name));
else
printf("\n", escape_string(temp_layer->layer_name));
}
if(get_method == TRUE)
printf("&layermode=%s", (exclude_layers == TRUE) ? "exclude" : "include");
else
printf("\n", (exclude_layers == TRUE) ? "exclude" : "include");
return;
}
/******************************************************************/
/************************ UTILITY FUNCTIONS ***********************/
/******************************************************************/
/* calculates how many "layers" separate parent and child - used by collapsed tree layout method */
int host_child_depth_separation(host *parent, host *child) {
int this_depth = 0;
int min_depth = 0;
int have_min_depth = FALSE;
host *temp_host;
if(child == NULL)
return -1;
if(parent == child)
return 0;
if(is_host_immediate_child_of_host(parent, child) == TRUE)
return 1;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(is_host_immediate_child_of_host(parent, temp_host) == TRUE) {
this_depth = host_child_depth_separation(temp_host, child);
if(this_depth >= 0 && (have_min_depth == FALSE || (have_min_depth == TRUE && (this_depth < min_depth)))) {
have_min_depth = TRUE;
min_depth = this_depth;
}
}
}
if(have_min_depth == FALSE)
return -1;
else
return min_depth + 1;
}
/* calculates how many hosts reside on a specific "layer" - used by collapsed tree layout method */
int number_of_host_layer_members(host *parent, int layer) {
int current_layer;
int layer_members = 0;
host *temp_host;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
current_layer = host_child_depth_separation(parent, temp_host);
if(current_layer == layer)
layer_members++;
}
return layer_members;
}
/* calculate max number of members on all "layers" beneath and including parent host - used by collapsed tree layout method */
int max_child_host_layer_members(host *parent) {
int current_layer;
int max_members = 1;
int current_members = 0;
for(current_layer = 1;; current_layer++) {
current_members = number_of_host_layer_members(parent, current_layer);
if(current_members <= 0)
break;
if(current_members > max_members)
max_members = current_members;
}
return max_members;
}
/* calculate max drawing width for host and children - used by balanced tree layout method */
int max_child_host_drawing_width(host *parent) {
host *temp_host;
int child_width = 0;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(is_host_immediate_child_of_host(parent, temp_host) == TRUE)
child_width += max_child_host_drawing_width(temp_host);
}
/* no children, so set width to 1 for this host */
if(child_width == 0)
return 1;
else
return child_width;
}
/* calculates number of services associated with a particular service */
int number_of_host_services(host *hst) {
service *temp_service;
int total_services = 0;
if(hst == NULL)
return 0;
/* check all the services */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
if(!strcmp(temp_service->host_name, hst->name))
total_services++;
}
return total_services;
}
/******************************************************************/
/***************** COORDINATE CALCULATION FUNCTIONS ***************/
/******************************************************************/
/* calculates coords of a host's children - used by balanced tree layout method */
void calculate_balanced_tree_coords(host *parent, int x, int y) {
int parent_drawing_width;
int start_drawing_x;
int current_drawing_x;
int this_drawing_width;
host *temp_host;
/* calculate total drawing width of parent host */
parent_drawing_width = max_child_host_drawing_width(parent);
/* calculate starting x coord */
start_drawing_x = x - (((DEFAULT_NODE_WIDTH * parent_drawing_width) + (DEFAULT_NODE_HSPACING * (parent_drawing_width - 1))) / 2);
current_drawing_x = start_drawing_x;
/* calculate coords for children */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(is_host_immediate_child_of_host(parent, temp_host) == TRUE) {
/* get drawing width of child host */
this_drawing_width = max_child_host_drawing_width(temp_host);
temp_host->x_2d = current_drawing_x + (((DEFAULT_NODE_WIDTH * this_drawing_width) + (DEFAULT_NODE_HSPACING * (this_drawing_width - 1))) / 2);
temp_host->y_2d = y + DEFAULT_NODE_HEIGHT + DEFAULT_NODE_VSPACING;
temp_host->have_2d_coords = TRUE;
temp_host->should_be_drawn = TRUE;
current_drawing_x += (this_drawing_width * DEFAULT_NODE_WIDTH) + ((this_drawing_width - 1) * DEFAULT_NODE_HSPACING) + DEFAULT_NODE_HSPACING;
/* recurse into child host ... */
calculate_balanced_tree_coords(temp_host, temp_host->x_2d, temp_host->y_2d);
}
}
return;
}
/* calculate coords of all hosts in circular layout method */
void calculate_circular_coords(void) {
int min_x = 0;
int min_y = 0;
int have_min_x = FALSE;
int have_min_y = FALSE;
host *temp_host;
/* calculate all host coords, starting with first layer */
calculate_circular_layer_coords(NULL, 0.0, 360.0, 1, CIRCULAR_DRAWING_RADIUS);
/* adjust all calculated coords so none are negative in x or y axis... */
/* calculate min x, y coords */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(have_min_x == FALSE || temp_host->x_2d < min_x) {
have_min_x = TRUE;
min_x = temp_host->x_2d;
}
if(have_min_y == FALSE || temp_host->y_2d < min_y) {
have_min_y = TRUE;
min_y = temp_host->y_2d;
}
}
/* offset all drawing coords by the min x,y coords we found */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(min_x < 0)
temp_host->x_2d -= min_x;
if(min_y < 0)
temp_host->y_2d -= min_y;
}
if(min_x < 0)
nagios_icon_x -= min_x;
if(min_y < 0)
nagios_icon_y -= min_y;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
temp_host->x_2d += (DEFAULT_NODE_WIDTH / 2);
temp_host->y_2d += (DEFAULT_NODE_HEIGHT / 2);
}
nagios_icon_x += (DEFAULT_NODE_WIDTH / 2);
nagios_icon_y += (DEFAULT_NODE_HEIGHT / 2);
return;
}
/* calculates coords of all hosts in a particular "layer" in circular layout method */
void calculate_circular_layer_coords(host *parent, double start_angle, double useable_angle, int layer, int radius) {
int parent_drawing_width = 0;
int this_drawing_width = 0;
int immediate_children = 0;
double current_drawing_angle = 0.0;
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;
/* get the total number of immediate children to this host */
immediate_children = number_of_immediate_child_hosts(parent);
/* bail out if we're done */
if(immediate_children == 0)
return;
/* 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;
/* calculate coords for children */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(is_host_immediate_child_of_host(parent, temp_host) == TRUE) {
/* get drawing width of child host */
this_drawing_width = max_child_host_drawing_width(temp_host);
/* calculate angle this host gets for drawing */
available_angle = useable_angle * ((double)this_drawing_width / (double)parent_drawing_width);
/* clip available angle if necessary */
/* this isn't really necessary, but helps keep things looking a bit more sane with less potential connection crossover */
clipped_available_angle = 360.0 / layer;
if(available_angle < clipped_available_angle)
clipped_available_angle = available_angle;
/* calculate the exact angle at which we should draw this child */
this_drawing_angle = current_drawing_angle + (available_angle / 2.0);
/* compensate for angle overflow */
while(this_drawing_angle >= 360.0)
this_drawing_angle -= 360.0;
while(this_drawing_angle < 0.0)
this_drawing_angle += 360.0;
/* calculate drawing coords of this host using good ol' geometry... */
x_coord = -(sin(-this_drawing_angle * (M_PI / 180.0)) * radius);
y_coord = -(sin((90 + this_drawing_angle) * (M_PI / 180.0)) * radius);
temp_host->x_2d = (int)x_coord;
temp_host->y_2d = (int)y_coord;
temp_host->have_2d_coords = TRUE;
temp_host->should_be_drawn = TRUE;
/* recurse into child host ... */
calculate_circular_layer_coords(temp_host, current_drawing_angle + ((available_angle - clipped_available_angle) / 2), clipped_available_angle, layer + 1, radius + CIRCULAR_DRAWING_RADIUS);
/* increment current drawing angle */
current_drawing_angle += available_angle;
}
}
return;
}
/* draws background "extras" for all hosts in circular markup layout */
void draw_circular_markup(void) {
/* calculate all host sections, starting with first layer */
draw_circular_layer_markup(NULL, 0.0, 360.0, 1, CIRCULAR_DRAWING_RADIUS);
return;
}
/* draws background "extras" for all hosts in a particular "layer" in circular markup layout */
void draw_circular_layer_markup(host *parent, double start_angle, double useable_angle, int layer, int radius) {
int parent_drawing_width = 0;
int this_drawing_width = 0;
int immediate_children = 0;
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;
host *temp_host;
int x_offset = 0;
int y_offset = 0;
int center_x = 0;
int center_y = 0;
int bgcolor = 0;
double arc_start_angle = 0.0;
double arc_end_angle = 0.0;
int translated_x = 0;
int translated_y = 0;
/* get the total number of immediate children to this host */
immediate_children = number_of_immediate_child_hosts(parent);
/* bail out if we're done */
if(immediate_children == 0)
return;
/* 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;
/* calculate coords for children */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(is_host_immediate_child_of_host(parent, temp_host) == TRUE) {
/* get drawing width of child host */
this_drawing_width = max_child_host_drawing_width(temp_host);
/* calculate angle this host gets for drawing */
available_angle = useable_angle * ((double)this_drawing_width / (double)parent_drawing_width);
/* clip available angle if necessary */
/* this isn't really necessary, but helps keep things looking a bit more sane with less potential connection crossover */
clipped_available_angle = 360.0 / layer;
if(available_angle < clipped_available_angle)
clipped_available_angle = available_angle;
/* calculate drawing coords of "leftmost" divider using good ol' geometry... */
x_coord[0] = -(sin(-current_drawing_angle * (M_PI / 180.0)) * (radius - (CIRCULAR_DRAWING_RADIUS / 2)));
y_coord[0] = -(sin((90 + current_drawing_angle) * (M_PI / 180.0)) * (radius - (CIRCULAR_DRAWING_RADIUS / 2)));
x_coord[1] = -(sin(-current_drawing_angle * (M_PI / 180.0)) * (radius + (CIRCULAR_DRAWING_RADIUS / 2)));
y_coord[1] = -(sin((90 + current_drawing_angle) * (M_PI / 180.0)) * (radius + (CIRCULAR_DRAWING_RADIUS / 2)));
/* calculate drawing coords of "rightmost" divider using good ol' geometry... */
x_coord[2] = -(sin((-(current_drawing_angle + available_angle)) * (M_PI / 180.0)) * (radius - (CIRCULAR_DRAWING_RADIUS / 2)));
y_coord[2] = -(sin((90 + current_drawing_angle + available_angle) * (M_PI / 180.0)) * (radius - (CIRCULAR_DRAWING_RADIUS / 2)));
x_coord[3] = -(sin((-(current_drawing_angle + available_angle)) * (M_PI / 180.0)) * (radius + (CIRCULAR_DRAWING_RADIUS / 2)));
y_coord[3] = -(sin((90 + current_drawing_angle + available_angle) * (M_PI / 180.0)) * (radius + (CIRCULAR_DRAWING_RADIUS / 2)));
x_offset = nagios_icon_x + (DEFAULT_NODE_WIDTH / 2) - canvas_x;
y_offset = nagios_icon_y + (DEFAULT_NODE_HEIGHT / 2) - canvas_y;
/* draw "slice" dividers */
if(immediate_children > 1 || layer > 1) {
/* draw "leftmost" divider */
gdImageLine(map_image, (int)x_coord[0] + x_offset, (int)y_coord[0] + y_offset, (int)x_coord[1] + x_offset, (int)y_coord[1] + y_offset, color_lightgrey);
/* draw "rightmost" divider */
gdImageLine(map_image, (int)x_coord[2] + x_offset, (int)y_coord[2] + y_offset, (int)x_coord[3] + x_offset, (int)y_coord[3] + y_offset, color_lightgrey);
}
/* determine arc drawing angles */
arc_start_angle = current_drawing_angle - 90.0;
while(arc_start_angle < 0.0)
arc_start_angle += 360.0;
arc_end_angle = arc_start_angle + available_angle;
/* draw inner arc */
gdImageArc(map_image, x_offset, y_offset, (radius - (CIRCULAR_DRAWING_RADIUS / 2)) * 2, (radius - (CIRCULAR_DRAWING_RADIUS / 2)) * 2, floor(arc_start_angle), ceil(arc_end_angle), color_lightgrey);
/* draw outer arc */
gdImageArc(map_image, x_offset, y_offset, (radius + (CIRCULAR_DRAWING_RADIUS / 2)) * 2, (radius + (CIRCULAR_DRAWING_RADIUS / 2)) * 2, floor(arc_start_angle), ceil(arc_end_angle), color_lightgrey);
/* determine center of "slice" and fill with appropriate color */
center_x = -(sin(-(current_drawing_angle + (available_angle / 2.0)) * (M_PI / 180.0)) * (radius));
center_y = -(sin((90 + current_drawing_angle + (available_angle / 2.0)) * (M_PI / 180.0)) * (radius));
translated_x = center_x + x_offset;
translated_y = center_y + y_offset;
/* determine background color */
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)
bgcolor = color_lightred;
else
bgcolor = color_lightgreen;
/* fill slice with background color */
/* the fill function only works with coordinates that are in bounds of the actual image */
if(translated_x > 0 && translated_y > 0 && translated_x < canvas_width && translated_y < canvas_height)
gdImageFillToBorder(map_image, translated_x, translated_y, color_lightgrey, bgcolor);
/* recurse into child host ... */
draw_circular_layer_markup(temp_host, current_drawing_angle + ((available_angle - clipped_available_angle) / 2), clipped_available_angle, layer + 1, radius + CIRCULAR_DRAWING_RADIUS);
/* increment current drawing angle */
current_drawing_angle += available_angle;
}
}
return;
}
nagios/cgi/statuswml.c 0000664 0000000 0000000 00000141710 12210155146 0015310 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* STATUSWML.C - Nagios Status CGI for WAP-enabled devices
*
* Copyright (c) 2001-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 10-15-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.
*************************************************************************/
#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"
extern time_t program_start;
extern char main_config_file[MAX_FILENAME_LENGTH];
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;
#define DISPLAY_HOST 0
#define DISPLAY_SERVICE 1
#define DISPLAY_HOSTGROUP 2
#define DISPLAY_INDEX 3
#define DISPLAY_PING 4
#define DISPLAY_TRACEROUTE 5
#define DISPLAY_QUICKSTATS 6
#define DISPLAY_PROCESS 7
#define DISPLAY_ALL_PROBLEMS 8
#define DISPLAY_UNHANDLED_PROBLEMS 9
#define DISPLAY_HOSTGROUP_SUMMARY 0
#define DISPLAY_HOSTGROUP_OVERVIEW 1
#define DISPLAY_HOST_SUMMARY 0
#define DISPLAY_HOST_SERVICES 1
void document_header(void);
void document_footer(void);
int process_cgivars(void);
int validate_arguments(void);
int is_valid_hostip(char *hostip);
int display_type = DISPLAY_INDEX;
int hostgroup_style = DISPLAY_HOSTGROUP_SUMMARY;
int host_style = DISPLAY_HOST_SUMMARY;
void display_index(void);
void display_host(void);
void display_host_services(void);
void display_service(void);
void display_hostgroup_summary(void);
void display_hostgroup_overview(void);
void display_ping(void);
void display_traceroute(void);
void display_quick_stats(void);
void display_process(void);
void display_problems(void);
char *host_name = "";
char *hostgroup_name = "";
char *service_desc = "";
char *ping_address = "";
char *traceroute_address = "";
int show_all_hostgroups = TRUE;
authdata current_authdata;
int main(void) {
int result = OK;
/* get the arguments passed in the URL */
process_cgivars();
/* reset internal variables */
reset_cgi_vars();
document_header();
/* validate arguments in URL */
result = validate_arguments();
if(result == ERROR) {
document_footer();
return ERROR;
}
/* read the CGI configuration file */
result = read_cgi_config_file(get_cgi_config_location());
if(result == ERROR) {
printf("
Error: Could not open CGI configuration file '%s' for reading!
\n", get_cgi_config_location());
document_footer();
return ERROR;
}
/* read the main configuration file */
result = read_main_config_file(main_config_file);
if(result == ERROR) {
printf("
Error: Could not open main configuration file '%s' for reading!
\n", 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) {
printf("
Error: Could not read some or all object configuration data!
\n");
document_footer();
return ERROR;
}
/* read all status data */
result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA);
if(result == ERROR) {
printf("
Error: Could not read host and service status information!
\n");
printf("\n");
printf("\n");
return;
}
/* displays service status */
void display_service(void) {
service *temp_service;
servicestatus *temp_servicestatus;
char last_check[MAX_DATETIME_LENGTH];
int days;
int hours;
int minutes;
int seconds;
time_t current_time;
time_t t;
char state_duration[48];
int found;
/**** MAIN SCREEN (CARD 1) ****/
printf("\n");
printf("
\n");
printf("Service '%s' on host '%s' \n", service_desc, host_name);
/* find the service */
temp_service = find_service(host_name, service_desc);
temp_servicestatus = find_servicestatus(host_name, service_desc);
if(temp_service == NULL || temp_servicestatus == NULL) {
printf("Error: Could not find service!\n");
printf("
\n");
return;
}
nagios/cgi/tac.c 0000664 0000000 0000000 00000163775 12210155146 0014033 0 ustar 00root root 0000000 0000000 /***********************************************************************
*
* 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.
*
* 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/getcgi.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
#define HEALTH_WARNING_PERCENTAGE 90
#define HEALTH_CRITICAL_PERCENTAGE 75
/* HOSTOUTAGE structure */
typedef struct hostoutage_struct {
host *hst;
int affected_child_hosts;
struct hostoutage_struct *next;
} hostoutage;
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_stylesheets_path[MAX_FILENAME_LENGTH];
extern char url_media_path[MAX_FILENAME_LENGTH];
extern int refresh_rate;
extern char *service_critical_sound;
extern char *service_warning_sound;
extern char *service_unknown_sound;
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;
void analyze_status_data(void);
void display_tac_overview(void);
void find_hosts_causing_outages(void);
void calculate_outage_effect_of_host(host *, int *);
int is_route_to_host_blocked(host *);
int number_of_host_services(host *);
void add_hostoutage(host *);
void free_hostoutage_list(void);
void document_header(int);
void document_footer(void);
int process_cgivars(void);
authdata current_authdata;
int embedded = FALSE;
int display_header = FALSE;
hostoutage *hostoutage_list = NULL;
int total_blocking_outages = 0;
int total_nonblocking_outages = 0;
int total_service_health = 0;
int total_host_health = 0;
int potential_service_health = 0;
int potential_host_health = 0;
double percent_service_health = 0.0;
double percent_host_health = 0.0;
int total_hosts = 0;
int total_services = 0;
int total_active_service_checks = 0;
int total_active_host_checks = 0;
int total_passive_service_checks = 0;
int total_passive_host_checks = 0;
double min_service_execution_time = -1.0;
double max_service_execution_time = -1.0;
double total_service_execution_time = 0.0;
double average_service_execution_time = -1.0;
double min_host_execution_time = -1.0;
double max_host_execution_time = -1.0;
double total_host_execution_time = 0.0;
double average_host_execution_time = -1.0;
double min_service_latency = -1.0;
double max_service_latency = -1.0;
double total_service_latency = 0.0;
double average_service_latency = -1.0;
double min_host_latency = -1.0;
double max_host_latency = -1.0;
double total_host_latency = 0.0;
double average_host_latency = -1.0;
int flapping_services = 0;
int flapping_hosts = 0;
int flap_disabled_services = 0;
int flap_disabled_hosts = 0;
int notification_disabled_services = 0;
int notification_disabled_hosts = 0;
int event_handler_disabled_services = 0;
int event_handler_disabled_hosts = 0;
int active_checks_disabled_services = 0;
int active_checks_disabled_hosts = 0;
int passive_checks_disabled_services = 0;
int passive_checks_disabled_hosts = 0;
int hosts_pending = 0;
int hosts_pending_disabled = 0;
int hosts_up_disabled = 0;
int hosts_up_unacknowledged = 0;
int hosts_up = 0;
int hosts_down_scheduled = 0;
int hosts_down_acknowledged = 0;
int hosts_down_disabled = 0;
int hosts_down_unacknowledged = 0;
int hosts_down = 0;
int hosts_unreachable_scheduled = 0;
int hosts_unreachable_acknowledged = 0;
int hosts_unreachable_disabled = 0;
int hosts_unreachable_unacknowledged = 0;
int hosts_unreachable = 0;
int services_pending = 0;
int services_pending_disabled = 0;
int services_ok_disabled = 0;
int services_ok_unacknowledged = 0;
int services_ok = 0;
int services_warning_host_problem = 0;
int services_warning_scheduled = 0;
int services_warning_acknowledged = 0;
int services_warning_disabled = 0;
int services_warning_unacknowledged = 0;
int services_warning = 0;
int services_unknown_host_problem = 0;
int services_unknown_scheduled = 0;
int services_unknown_acknowledged = 0;
int services_unknown_disabled = 0;
int services_unknown_unacknowledged = 0;
int services_unknown = 0;
int services_critical_host_problem = 0;
int services_critical_scheduled = 0;
int services_critical_acknowledged = 0;
int services_critical_disabled = 0;
int services_critical_unacknowledged = 0;
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();
/* 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);
/* get authentication information */
get_authentication_information(¤t_authdata);
if(display_header == TRUE) {
/* begin top table */
printf("
\n");
printf("
\n");
/* left column of top table - info box */
printf("
\n");
display_info_table("Tactical Status Overview", TRUE, ¤t_authdata);
printf("
\n");
/* middle column of top table - log file navigation options */
printf("
\n");
printf("
\n");
/* right hand column of top row */
printf("
\n");
printf("
\n");
/* end of top table */
printf("
\n");
printf("
\n");
printf("\n");
}
#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;
else if(hosts_down_unacknowledged > 0 && host_down_sound != NULL)
sound = host_down_sound;
else if(services_critical_unacknowledged > 0 && service_critical_sound != NULL)
sound = service_critical_sound;
else if(services_warning_unacknowledged > 0 && service_warning_sound != NULL)
sound = service_warning_sound;
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("");
}
/**** display main tac screen ****/
display_tac_overview();
#ifdef DEBUG
time(&t9);
#endif
document_footer();
/* free memory allocated to the host outage list */
free_hostoutage_list();
/* 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;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
time_t expire_time;
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
printf("Refresh: %d\r\n", refresh_rate);
time(¤t_time);
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: text/html\r\n\r\n");
if(embedded == TRUE)
return;
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("Nagios Tactical Monitoring Overview\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("\n", url_stylesheets_path, COMMON_CSS);
printf("\n", url_stylesheets_path, TAC_CSS);
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(TAC_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(TAC_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
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 embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
/* we found the noheader option */
else if(!strcmp(variables[x], "noheader"))
display_header = FALSE;
/* we received an invalid argument */
else
error = TRUE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
void analyze_status_data(void) {
servicestatus *temp_servicestatus;
service *temp_service;
hoststatus *temp_hoststatus;
host *temp_host;
int problem = TRUE;
/* check all services */
for(temp_servicestatus = servicestatus_list; temp_servicestatus != NULL; temp_servicestatus = temp_servicestatus->next) {
/* see if user is authorized to view this service */
temp_service = find_service(temp_servicestatus->host_name, temp_servicestatus->description);
if(is_authorized_for_service(temp_service, ¤t_authdata) == FALSE)
continue;
/******** CHECK FEATURES *******/
/* check flapping */
if(temp_servicestatus->flap_detection_enabled == FALSE)
flap_disabled_services++;
else if(temp_servicestatus->is_flapping == TRUE)
flapping_services++;
/* check notifications */
if(temp_servicestatus->notifications_enabled == FALSE)
notification_disabled_services++;
/* check event handler */
if(temp_servicestatus->event_handler_enabled == FALSE)
event_handler_disabled_services++;
/* active check execution */
if(temp_servicestatus->checks_enabled == FALSE)
active_checks_disabled_services++;
/* passive check acceptance */
if(temp_servicestatus->accept_passive_service_checks == FALSE)
passive_checks_disabled_services++;
/********* CHECK STATUS ********/
problem = TRUE;
if(temp_servicestatus->status == SERVICE_OK) {
if(temp_servicestatus->checks_enabled == FALSE)
services_ok_disabled++;
else
services_ok_unacknowledged++;
services_ok++;
}
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)) {
services_warning_host_problem++;
problem = FALSE;
}
if(temp_servicestatus->scheduled_downtime_depth > 0) {
services_warning_scheduled++;
problem = FALSE;
}
if(temp_servicestatus->problem_has_been_acknowledged == TRUE) {
services_warning_acknowledged++;
problem = FALSE;
}
if(temp_servicestatus->checks_enabled == FALSE) {
services_warning_disabled++;
problem = FALSE;
}
if(problem == TRUE)
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)) {
services_unknown_host_problem++;
problem = FALSE;
}
if(temp_servicestatus->scheduled_downtime_depth > 0) {
services_unknown_scheduled++;
problem = FALSE;
}
if(temp_servicestatus->problem_has_been_acknowledged == TRUE) {
services_unknown_acknowledged++;
problem = FALSE;
}
if(temp_servicestatus->checks_enabled == FALSE) {
services_unknown_disabled++;
problem = FALSE;
}
if(problem == TRUE)
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)) {
services_critical_host_problem++;
problem = FALSE;
}
if(temp_servicestatus->scheduled_downtime_depth > 0) {
services_critical_scheduled++;
problem = FALSE;
}
if(temp_servicestatus->problem_has_been_acknowledged == TRUE) {
services_critical_acknowledged++;
problem = FALSE;
}
if(temp_servicestatus->checks_enabled == FALSE) {
services_critical_disabled++;
problem = FALSE;
}
if(problem == TRUE)
services_critical_unacknowledged++;
services_critical++;
}
else if(temp_servicestatus->status == SERVICE_PENDING) {
if(temp_servicestatus->checks_enabled == FALSE)
services_pending_disabled++;
services_pending++;
}
/* get health stats */
if(temp_servicestatus->status == SERVICE_OK)
total_service_health += 2;
else if(temp_servicestatus->status == SERVICE_WARNING || temp_servicestatus->status == SERVICE_UNKNOWN)
total_service_health++;
if(temp_servicestatus->status != SERVICE_PENDING)
potential_service_health += 2;
/* calculate execution time and latency stats */
if(temp_servicestatus->check_type == SERVICE_CHECK_ACTIVE) {
total_active_service_checks++;
if(min_service_latency == -1.0 || temp_servicestatus->latency < min_service_latency)
min_service_latency = temp_servicestatus->latency;
if(max_service_latency == -1.0 || temp_servicestatus->latency > max_service_latency)
max_service_latency = temp_servicestatus->latency;
if(min_service_execution_time == -1.0 || temp_servicestatus->execution_time < min_service_execution_time)
min_service_execution_time = temp_servicestatus->execution_time;
if(max_service_execution_time == -1.0 || temp_servicestatus->execution_time > max_service_execution_time)
max_service_execution_time = temp_servicestatus->execution_time;
total_service_latency += temp_servicestatus->latency;
total_service_execution_time += temp_servicestatus->execution_time;
}
else
total_passive_service_checks++;
total_services++;
}
/* check all hosts */
for(temp_hoststatus = hoststatus_list; temp_hoststatus != NULL; temp_hoststatus = temp_hoststatus->next) {
/* see if user is authorized to view this host */
temp_host = find_host(temp_hoststatus->host_name);
if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE)
continue;
/******** CHECK FEATURES *******/
/* check flapping */
if(temp_hoststatus->flap_detection_enabled == FALSE)
flap_disabled_hosts++;
else if(temp_hoststatus->is_flapping == TRUE)
flapping_hosts++;
/* check notifications */
if(temp_hoststatus->notifications_enabled == FALSE)
notification_disabled_hosts++;
/* check event handler */
if(temp_hoststatus->event_handler_enabled == FALSE)
event_handler_disabled_hosts++;
/* active check execution */
if(temp_hoststatus->checks_enabled == FALSE)
active_checks_disabled_hosts++;
/* passive check acceptance */
if(temp_hoststatus->accept_passive_host_checks == FALSE)
passive_checks_disabled_hosts++;
/********* CHECK STATUS ********/
problem = TRUE;
if(temp_hoststatus->status == HOST_UP) {
if(temp_hoststatus->checks_enabled == FALSE)
hosts_up_disabled++;
else
hosts_up_unacknowledged++;
hosts_up++;
}
else if(temp_hoststatus->status == HOST_DOWN) {
if(temp_hoststatus->scheduled_downtime_depth > 0) {
hosts_down_scheduled++;
problem = FALSE;
}
if(temp_hoststatus->problem_has_been_acknowledged == TRUE) {
hosts_down_acknowledged++;
problem = FALSE;
}
if(temp_hoststatus->checks_enabled == FALSE) {
hosts_down_disabled++;
problem = FALSE;
}
if(problem == TRUE)
hosts_down_unacknowledged++;
hosts_down++;
}
else if(temp_hoststatus->status == HOST_UNREACHABLE) {
if(temp_hoststatus->scheduled_downtime_depth > 0) {
hosts_unreachable_scheduled++;
problem = FALSE;
}
if(temp_hoststatus->problem_has_been_acknowledged == TRUE) {
hosts_unreachable_acknowledged++;
problem = FALSE;
}
if(temp_hoststatus->checks_enabled == FALSE) {
hosts_unreachable_disabled++;
problem = FALSE;
}
if(problem == TRUE)
hosts_unreachable_unacknowledged++;
hosts_unreachable++;
}
else if(temp_hoststatus->status == HOST_PENDING) {
if(temp_hoststatus->checks_enabled == FALSE)
hosts_pending_disabled++;
hosts_pending++;
}
/* get health stats */
if(temp_hoststatus->status == 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) {
total_active_host_checks++;
if(min_host_latency == -1.0 || temp_hoststatus->latency < min_host_latency)
min_host_latency = temp_hoststatus->latency;
if(max_host_latency == -1.0 || temp_hoststatus->latency > max_host_latency)
max_host_latency = temp_hoststatus->latency;
if(min_host_execution_time == -1.0 || temp_hoststatus->execution_time < min_host_execution_time)
min_host_execution_time = temp_hoststatus->execution_time;
if(max_host_execution_time == -1.0 || temp_hoststatus->execution_time > max_host_execution_time)
max_host_execution_time = temp_hoststatus->execution_time;
total_host_latency += temp_hoststatus->latency;
total_host_execution_time += temp_hoststatus->execution_time;
}
else
total_passive_host_checks++;
total_hosts++;
}
/* calculate service health */
if(potential_service_health == 0)
percent_service_health = 0.0;
else
percent_service_health = ((double)total_service_health / (double)potential_service_health) * 100.0;
/* calculate host health */
if(potential_host_health == 0)
percent_host_health = 0.0;
else
percent_host_health = ((double)total_host_health / (double)potential_host_health) * 100.0;
/* calculate service latency */
if(total_service_latency == 0L)
average_service_latency = 0.0;
else
average_service_latency = ((double)total_service_latency / (double)total_active_service_checks);
/* calculate host latency */
if(total_host_latency == 0L)
average_host_latency = 0.0;
else
average_host_latency = ((double)total_host_latency / (double)total_active_host_checks);
/* calculate service execution time */
if(total_service_execution_time == 0.0)
average_service_execution_time = 0.0;
else
average_service_execution_time = ((double)total_service_execution_time / (double)total_active_service_checks);
/* calculate host execution time */
if(total_host_execution_time == 0.0)
average_host_execution_time = 0.0;
else
average_host_execution_time = ((double)total_host_execution_time / (double)total_active_host_checks);
return;
}
/* determine what hosts are causing network outages */
void find_hosts_causing_outages(void) {
hoststatus *temp_hoststatus;
hostoutage *temp_hostoutage;
host *temp_host;
/* user must be authorized for all hosts in order to see outages */
if(is_authorized_for_all_hosts(¤t_authdata) == FALSE)
return;
/* check all hosts */
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) {
/* find the host entry */
temp_host = find_host(temp_hoststatus->host_name);
if(temp_host == NULL)
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);
}
}
/* check all hosts that are causing problems and calculate the extent of the problem */
for(temp_hostoutage = hostoutage_list; temp_hostoutage != NULL; temp_hostoutage = temp_hostoutage->next) {
/* calculate the outage effect of this particular hosts */
calculate_outage_effect_of_host(temp_hostoutage->hst, &temp_hostoutage->affected_child_hosts);
if(temp_hostoutage->affected_child_hosts > 1)
total_blocking_outages++;
else
total_nonblocking_outages++;
}
return;
}
/* adds a host outage entry */
void add_hostoutage(host *hst) {
hostoutage *new_hostoutage;
/* allocate memory for a new structure */
new_hostoutage = (hostoutage *)malloc(sizeof(hostoutage));
if(new_hostoutage == NULL)
return;
new_hostoutage->hst = hst;
new_hostoutage->affected_child_hosts = 0;
/* add the structure to the head of the list in memory */
new_hostoutage->next = hostoutage_list;
hostoutage_list = new_hostoutage;
return;
}
/* frees all memory allocated to the host outage list */
void free_hostoutage_list(void) {
hostoutage *this_hostoutage;
hostoutage *next_hostoutage;
for(this_hostoutage = hostoutage_list; this_hostoutage != NULL; this_hostoutage = next_hostoutage) {
next_hostoutage = this_hostoutage->next;
free(this_hostoutage);
}
return;
}
/* calculates network outage effect of a particular host being down or unreachable */
void calculate_outage_effect_of_host(host *hst, int *affected_hosts) {
int total_child_hosts_affected = 0;
int temp_child_hosts_affected = 0;
host *temp_host;
/* find all child hosts of this host */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
/* skip this host if it is not a child */
if(is_host_immediate_child_of_host(hst, temp_host) == FALSE)
continue;
/* calculate the outage effect of the child */
calculate_outage_effect_of_host(temp_host, &temp_child_hosts_affected);
/* keep a running total of outage effects */
total_child_hosts_affected += temp_child_hosts_affected;
}
*affected_hosts = total_child_hosts_affected + 1;
return;
}
/* tests whether or not a host is "blocked" by upstream parents (host is already assumed to be down or unreachable) */
int is_route_to_host_blocked(host *hst) {
hostsmember *temp_hostsmember;
hoststatus *temp_hoststatus;
/* if the host has no parents, it is not being blocked by anyone */
if(hst->parent_hosts == NULL)
return FALSE;
/* check all parent hosts */
for(temp_hostsmember = hst->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
/* find the parent host's status */
temp_hoststatus = find_hoststatus(temp_hostsmember->host_name);
if(temp_hoststatus == NULL)
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)
return FALSE;
}
return TRUE;
}
void display_tac_overview(void) {
char host_health_image[16];
char service_health_image[16];
printf("
\n");
}
if(mode == CREATE_IMAGE || (mode == CREATE_HTML && use_map == TRUE)) {
/* draw timestamps */
draw_timestamps();
/* draw horizontal lines */
draw_horizontal_grid_lines();
/* draw state time breakdowns */
draw_time_breakdowns();
}
if(mode == CREATE_IMAGE) {
/* use STDOUT for writing the image data... */
image_file = stdout;
#ifndef DEBUG
/* write the image to file */
gdImagePng(trends_image, image_file);
#endif
#ifdef DEBUG
image_file = fopen("trends.png", "w");
if(image_file == NULL)
printf("Could not open trends.png for writing!\n");
else {
gdImagePng(trends_image, image_file);
fclose(image_file);
}
#endif
/* free memory allocated to image */
gdImageDestroy(trends_image);
}
}
/* show user a selection of hosts and services to choose from... */
if(display_type == DISPLAY_NO_TRENDS || input_type != GET_INPUT_NONE) {
/* ask the user for what host they want a report for */
if(input_type == GET_INPUT_HOST_TARGET) {
printf("
\n");
printf("
Step 2: Select Host
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
\n");
}
/* ask the user for what service they want a report for */
else if(input_type == GET_INPUT_SERVICE_TARGET) {
printf("\n");
printf("
\n");
printf("
Step 2: Select Service
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
\n");
}
/* ask the user for report range and options */
else if(input_type == GET_INPUT_OPTIONS) {
time(¤t_time);
t = localtime(¤t_time);
start_day = 1;
start_year = t->tm_year + 1900;
end_day = t->tm_mday;
end_year = t->tm_year + 1900;
printf("
\n");
printf("
Step 3: Select Report Options
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
\n");
/*
printf("
\n");
printf("Note: Choosing the 'suppress image map' option will make the report run approximately twice as fast as it would otherwise, but it will prevent you from being able to zoom in on specific time periods.\n");
printf("
\n");
*/
}
/* as the user whether they want a graph for a host or service */
else {
printf("
\n");
printf("
Step 1: Select Report Type
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
\n");
}
}
document_footer();
/* free memory allocated to the archived state data list */
free_archived_state_list();
/* free all other allocated memory */
free_memory();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
time_t expire_time;
if(mode == CREATE_HTML) {
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
time(¤t_time);
get_time_string(¤t_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
printf("Last-Modified: %s\r\n", date_time);
expire_time = (time_t)0;
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");
if(embedded == TRUE)
return;
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("Nagios Trends\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("\n", url_stylesheets_path, COMMON_CSS);
printf("\n", url_stylesheets_path, TRENDS_CSS);
}
/* write JavaScript code for popup window */
if(display_type != DISPLAY_NO_TRENDS)
write_popup_code();
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(TRENDS_CGI, SSI_HEADER);
printf("\n");
}
else {
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
time(¤t_time);
get_time_string(¤t_time, date_time, 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, sizeof(date_time), HTTP_DATE_TIME);
printf("Expires: %s\r\n", date_time);
printf("Content-Type: image/png\r\n\r\n");
}
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
if(mode == CREATE_HTML) {
/* include user SSI footer */
include_ssi_files(TRENDS_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
}
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
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) {
x++;
continue;
}
/* we found the host argument */
else if(!strcmp(variables[x], "host")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((host_name = (char *)strdup(variables[x])) == NULL)
host_name = "";
strip_html_brackets(host_name);
display_type = DISPLAY_HOST_TRENDS;
}
/* we found the node width argument */
else if(!strcmp(variables[x], "service")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((svc_description = (char *)strdup(variables[x])) == NULL)
svc_description = "";
strip_html_brackets(svc_description);
display_type = DISPLAY_SERVICE_TRENDS;
}
/* we found first time argument */
else if(!strcmp(variables[x], "t1")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
t1 = (time_t)strtoul(variables[x], NULL, 10);
timeperiod_type = TIMEPERIOD_CUSTOM;
}
/* we found first time argument */
else if(!strcmp(variables[x], "t2")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
t2 = (time_t)strtoul(variables[x], NULL, 10);
timeperiod_type = TIMEPERIOD_CUSTOM;
}
/* we found the image creation option */
else if(!strcmp(variables[x], "createimage")) {
mode = CREATE_IMAGE;
}
/* we found the assume initial states option */
else if(!strcmp(variables[x], "assumeinitialstates")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "yes"))
assume_initial_states = TRUE;
else
assume_initial_states = FALSE;
}
/* we found the initial assumed host state option */
else if(!strcmp(variables[x], "initialassumedhoststate")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
initial_assumed_host_state = atoi(variables[x]);
}
/* we found the initial assumed service state option */
else if(!strcmp(variables[x], "initialassumedservicestate")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
initial_assumed_service_state = atoi(variables[x]);
}
/* we found the assume state during program not running option */
else if(!strcmp(variables[x], "assumestatesduringnotrunning")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "yes"))
assume_states_during_notrunning = TRUE;
else
assume_states_during_notrunning = FALSE;
}
/* we found the assume state retention option */
else if(!strcmp(variables[x], "assumestateretention")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "yes"))
assume_state_retention = TRUE;
else
assume_state_retention = FALSE;
}
/* we found the include soft states option */
else if(!strcmp(variables[x], "includesoftstates")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "yes"))
include_soft_states = TRUE;
else
include_soft_states = FALSE;
}
/* we found the zoom factor argument */
else if(!strcmp(variables[x], "zoom")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
zoom_factor = atoi(variables[x]);
if(zoom_factor == 0)
zoom_factor = 1;
}
/* we found the backtrack archives argument */
else if(!strcmp(variables[x], "backtrack")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
backtrack_archives = atoi(variables[x]);
if(backtrack_archives < 0)
backtrack_archives = 0;
if(backtrack_archives > MAX_ARCHIVE_BACKTRACKS)
backtrack_archives = MAX_ARCHIVE_BACKTRACKS;
}
/* we found the standard timeperiod argument */
else if(!strcmp(variables[x], "timeperiod")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "today"))
timeperiod_type = TIMEPERIOD_TODAY;
else if(!strcmp(variables[x], "yesterday"))
timeperiod_type = TIMEPERIOD_YESTERDAY;
else if(!strcmp(variables[x], "thisweek"))
timeperiod_type = TIMEPERIOD_THISWEEK;
else if(!strcmp(variables[x], "lastweek"))
timeperiod_type = TIMEPERIOD_LASTWEEK;
else if(!strcmp(variables[x], "thismonth"))
timeperiod_type = TIMEPERIOD_THISMONTH;
else if(!strcmp(variables[x], "lastmonth"))
timeperiod_type = TIMEPERIOD_LASTMONTH;
else if(!strcmp(variables[x], "thisquarter"))
timeperiod_type = TIMEPERIOD_THISQUARTER;
else if(!strcmp(variables[x], "lastquarter"))
timeperiod_type = TIMEPERIOD_LASTQUARTER;
else if(!strcmp(variables[x], "thisyear"))
timeperiod_type = TIMEPERIOD_THISYEAR;
else if(!strcmp(variables[x], "lastyear"))
timeperiod_type = TIMEPERIOD_LASTYEAR;
else if(!strcmp(variables[x], "nextproblem"))
timeperiod_type = TIMEPERIOD_NEXTPROBLEM;
else if(!strcmp(variables[x], "last24hours"))
timeperiod_type = TIMEPERIOD_LAST24HOURS;
else if(!strcmp(variables[x], "last7days"))
timeperiod_type = TIMEPERIOD_LAST7DAYS;
else if(!strcmp(variables[x], "last31days"))
timeperiod_type = TIMEPERIOD_LAST31DAYS;
else if(!strcmp(variables[x], "custom"))
timeperiod_type = TIMEPERIOD_CUSTOM;
else
continue;
convert_timeperiod_to_times(timeperiod_type);
}
/* we found time argument */
else if(!strcmp(variables[x], "smon")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_month = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "sday")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_day = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "syear")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_year = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "smin")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_minute = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "ssec")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_second = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "shour")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_hour = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "emon")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_month = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "eday")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_day = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "eyear")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_year = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "emin")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_minute = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "esec")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_second = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if(!strcmp(variables[x], "ehour")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_hour = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found the embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
/* we found the noheader option */
else if(!strcmp(variables[x], "noheader"))
display_header = FALSE;
/* we found the nopopups option */
else if(!strcmp(variables[x], "nopopups"))
display_popups = FALSE;
/* we found the nomap option */
else if(!strcmp(variables[x], "nomap")) {
display_popups = FALSE;
use_map = FALSE;
}
/* we found the input option */
else if(!strcmp(variables[x], "input")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "gethost"))
input_type = GET_INPUT_HOST_TARGET;
else if(!strcmp(variables[x], "getservice"))
input_type = GET_INPUT_SERVICE_TARGET;
else if(!strcmp(variables[x], "getoptions"))
input_type = GET_INPUT_OPTIONS;
else
input_type = GET_INPUT_TARGET_TYPE;
}
/* we found the small image option */
else if(!strcmp(variables[x], "smallimage"))
small_image = TRUE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
/* top level routine for graphic all trend data */
void graph_all_trend_data(void) {
archived_state *temp_as;
archived_state *last_as;
time_t a;
time_t b;
time_t current_time;
int current_state = AS_NO_DATA;
int have_some_real_data = FALSE;
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;
time(¤t_time);
/* if left hand of graph is after current time, we can't do anything at all.... */
if(t1 > current_time)
return;
/* find current state for host or service */
if(display_type == DISPLAY_HOST_TRENDS)
hststatus = find_hoststatus(host_name);
else
svcstatus = find_servicestatus(host_name, svc_description);
/************************************/
/* INSERT CURRENT STATE (IF WE CAN) */
/************************************/
/* if current time DOES NOT fall within graph bounds, so we can't do anything as far as assuming current state */
/* 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)) {
/* 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)
last_known_state = AS_HOST_DOWN;
else if(hststatus->status == 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 {
if(svcstatus != NULL) {
if(svcstatus->status == SERVICE_OK)
last_known_state = AS_SVC_OK;
else if(svcstatus->status == SERVICE_WARNING)
last_known_state = AS_SVC_WARNING;
else if(svcstatus->status == SERVICE_CRITICAL)
last_known_state = AS_SVC_CRITICAL;
else if(svcstatus->status == SERVICE_UNKNOWN)
last_known_state = AS_SVC_UNKNOWN;
/* 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;
}
}
}
/******************************************/
/* INSERT FIRST ASSUMED STATE (IF WE CAN) */
/******************************************/
if((display_type == DISPLAY_HOST_TRENDS && initial_assumed_host_state != AS_NO_DATA) || (display_type == DISPLAY_SERVICE_TRENDS && initial_assumed_service_state != AS_NO_DATA)) {
/* see if its okay to assume initial state for this subject */
error = FALSE;
if(display_type == DISPLAY_SERVICE_TRENDS) {
if(initial_assumed_service_state != AS_SVC_OK && initial_assumed_service_state != AS_SVC_WARNING && initial_assumed_service_state != AS_SVC_UNKNOWN && initial_assumed_service_state != AS_SVC_CRITICAL && initial_assumed_service_state != AS_CURRENT_STATE)
error = TRUE;
else
initial_assumed_state = initial_assumed_service_state;
if(initial_assumed_service_state == AS_CURRENT_STATE && svcstatus == NULL)
error = TRUE;
}
else {
if(initial_assumed_host_state != AS_HOST_UP && initial_assumed_host_state != AS_HOST_DOWN && initial_assumed_host_state != AS_HOST_UNREACHABLE && initial_assumed_host_state != AS_CURRENT_STATE)
error = TRUE;
else
initial_assumed_state = initial_assumed_host_state;
if(initial_assumed_host_state == AS_CURRENT_STATE && hststatus == NULL)
error = TRUE;
}
/* get the current state if applicable */
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:
initial_assumed_state = AS_HOST_DOWN;
break;
case HOST_UNREACHABLE:
initial_assumed_state = AS_HOST_UNREACHABLE;
break;
case HOST_UP:
initial_assumed_state = AS_HOST_UP;
break;
default:
error = TRUE;
break;
}
}
else {
switch(svcstatus->status) {
case SERVICE_OK:
initial_assumed_state = AS_SVC_OK;
break;
case SERVICE_WARNING:
initial_assumed_state = AS_SVC_WARNING;
break;
case SERVICE_UNKNOWN:
initial_assumed_state = AS_SVC_UNKNOWN;
break;
case SERVICE_CRITICAL:
initial_assumed_state = AS_SVC_CRITICAL;
break;
default:
error = TRUE;
break;
}
}
}
if(error == FALSE) {
/* add this assumed state entry before any entries in the list and <= t1 */
if(as_list == NULL)
initial_assumed_time = t1;
else if(as_list->time_stamp > t1)
initial_assumed_time = t1;
else
initial_assumed_time = as_list->time_stamp - 1;
if(display_type == DISPLAY_HOST_TRENDS)
add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Host State Assumed (Faked Log Entry)");
else
add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Service State Assumed (Faked Log Entry)");
}
}
/**************************************/
/* BAIL OUT IF WE DON'T HAVE ANYTHING */
/**************************************/
have_some_real_data = FALSE;
for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
if(temp_as->entry_type != AS_NO_DATA && temp_as->entry_type != AS_PROGRAM_START && temp_as->entry_type != AS_PROGRAM_END) {
have_some_real_data = TRUE;
break;
}
}
if(have_some_real_data == FALSE)
return;
/* if we're creating the HTML, start map code... */
if(mode == CREATE_HTML)
printf("\n");
return;
}
/* 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;
int height = 0;
double start_pixel_ratio;
double end_pixel_ratio;
char temp_buffer[MAX_INPUT_BUFFER];
char state_string[MAX_INPUT_BUFFER];
char end_timestring[MAX_INPUT_BUFFER];
char start_timestring[MAX_INPUT_BUFFER];
time_t center_time;
time_t next_start_time;
time_t next_end_time;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
/* can't graph if we don't have data... */
if(first_state == AS_NO_DATA || last_state == AS_NO_DATA)
return;
if(first_state == AS_PROGRAM_START && (last_state == AS_PROGRAM_END || last_state == AS_PROGRAM_START)) {
if(assume_initial_states == FALSE)
return;
}
if(first_state == AS_PROGRAM_END) {
if(assume_states_during_notrunning == TRUE)
first_state = last_known_state;
else
return;
}
/* special case if first entry was program start */
if(first_state == AS_PROGRAM_START) {
#ifdef DEBUG
printf("First state=program start!\n");
#endif
if(assume_initial_states == TRUE) {
#ifdef DEBUG
printf("\tWe are assuming initial states...\n");
#endif
if(assume_state_retention == TRUE) {
start_state = last_known_state;
#ifdef DEBUG
printf("\tWe are assuming state retention (%d)...\n", start_state);
#endif
}
else {
#ifdef DEBUG
printf("\tWe are NOT assuming state retention...\n");
#endif
if(display_type == DISPLAY_HOST_TRENDS)
start_state = AS_HOST_UP;
else
start_state = AS_SVC_OK;
}
}
else {
#ifdef DEBUG
printf("We ARE NOT assuming initial states!\n");
#endif
return;
}
}
else {
start_state = first_state;
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));
printf("\tto %s", ctime(&end_time));
#endif
if(start_time < t1)
start_time = t1;
if(end_time > t2)
end_time = t2;
if(end_time < t1 || start_time > t2)
return;
/* calculate the first and last pixels to use */
if(start_time == t1)
start_pixel = 0;
else {
start_pixel_ratio = ((double)(start_time - t1)) / ((double)(t2 - t1));
start_pixel = (int)(start_pixel_ratio * (drawing_width - 1));
}
if(end_time == t1)
end_pixel = 0;
else {
end_pixel_ratio = ((double)(end_time - t1)) / ((double)(t2 - t1));
end_pixel = (int)(end_pixel_ratio * (drawing_width - 1));
}
#ifdef DEBUG
printf("\tPixel %d to %d\n\n", start_pixel, end_pixel);
#endif
/* we're creating the image, so draw... */
if(mode == CREATE_IMAGE) {
/* figure out the color to use for drawing */
switch(start_state) {
case AS_HOST_UP:
color_to_use = color_green;
height = 60;
break;
case AS_HOST_DOWN:
color_to_use = color_red;
height = 40;
break;
case AS_HOST_UNREACHABLE:
color_to_use = color_darkred;
height = 20;
break;
case AS_SVC_OK:
color_to_use = color_green;
height = 80;
break;
case AS_SVC_WARNING:
color_to_use = color_yellow;
height = 60;
break;
case AS_SVC_UNKNOWN:
color_to_use = color_orange;
height = 40;
break;
case AS_SVC_CRITICAL:
color_to_use = color_red;
height = 20;
break;
default:
color_to_use = color_black;
height = 0;
break;
}
/* draw a rectangle */
if(start_state != AS_NO_DATA)
gdImageFilledRectangle(trends_image, start_pixel + drawing_x_offset, drawing_height - height + drawing_y_offset, end_pixel + drawing_x_offset, drawing_height + drawing_y_offset, color_to_use);
}
/* else we're creating the HTML, so write map area code... */
else {
/* figure out the the state string to use */
switch(start_state) {
case AS_HOST_UP:
strcpy(state_string, "UP");
height = 60;
break;
case AS_HOST_DOWN:
strcpy(state_string, "DOWN");
height = 40;
break;
case AS_HOST_UNREACHABLE:
strcpy(state_string, "UNREACHABLE");
height = 20;
break;
case AS_SVC_OK:
strcpy(state_string, "OK");
height = 80;
break;
case AS_SVC_WARNING:
strcpy(state_string, "WARNING");
height = 60;
break;
case AS_SVC_UNKNOWN:
strcpy(state_string, "UNKNOWN");
height = 40;
break;
case AS_SVC_CRITICAL:
strcpy(state_string, "CRITICAL");
height = 20;
break;
default:
strcpy(state_string, "?");
height = 5;
break;
}
/* get the center of this time range */
center_time = start_time + ((end_time - start_time) / 2);
/* determine next start and end time range with zoom factor */
if(zoom_factor > 0) {
next_start_time = center_time - (((t2 - t1) / 2) / zoom_factor);
next_end_time = center_time + (((t2 - t1) / 2) / zoom_factor);
}
else {
next_start_time = center_time + (((t2 - t1) / 2) * zoom_factor);
next_end_time = center_time - (((t2 - t1) / 2) * zoom_factor);
}
printf(" 0)
printf("&backtrack=%d", backtrack_archives);
printf("&zoom=%d", zoom_factor);
printf("' ");
/* display popup text */
if(display_popups == TRUE) {
snprintf(start_timestring, sizeof(start_timestring) - 1, "%s", ctime(&real_start_time));
start_timestring[sizeof(start_timestring) - 1] = '\x0';
start_timestring[strlen(start_timestring) - 1] = '\x0';
snprintf(end_timestring, sizeof(end_timestring) - 1, "%s", ctime(&end_time));
end_timestring[sizeof(end_timestring) - 1] = '\x0';
end_timestring[strlen(end_timestring) - 1] = '\x0';
/* calculate total time in this state */
get_time_breakdown((time_t)(end_time - start_time), &days, &hours, &minutes, &seconds);
/* sanitize plugin output */
sanitize_plugin_output(state_info);
printf("onMouseOver='showPopup(\"");
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s Time Range: %s to %s Duration: %dd %dh %dm %ds State Info: %s", state_string, start_timestring, end_timestring, days, hours, minutes, seconds, (state_info == NULL) ? "N/A" : state_info);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
printf("%s", temp_buffer);
printf("\",event)' onMouseOut='hidePopup()'");
}
printf(">\n");
}
/* calculate time in this state */
switch(start_state) {
case AS_HOST_UP:
time_up += (unsigned long)(end_time - start_time);
break;
case AS_HOST_DOWN:
time_down += (unsigned long)(end_time - start_time);
break;
case AS_HOST_UNREACHABLE:
time_unreachable += (unsigned long)(end_time - start_time);
break;
case AS_SVC_OK:
time_ok += (unsigned long)(end_time - start_time);
break;
case AS_SVC_WARNING:
time_warning += (unsigned long)(end_time - start_time);
break;
case AS_SVC_UNKNOWN:
time_unknown += (unsigned long)(end_time - start_time);
break;
case AS_SVC_CRITICAL:
time_critical += (unsigned long)(end_time - start_time);
break;
default:
break;
}
return;
}
/* convert current host state to archived state value */
int convert_host_state_to_archived_state(int current_status) {
if(current_status == HOST_UP)
return AS_HOST_UP;
if(current_status == HOST_DOWN)
return AS_HOST_DOWN;
if(current_status == HOST_UNREACHABLE)
return AS_HOST_UNREACHABLE;
return AS_NO_DATA;
}
/* convert current service state to archived state value */
int convert_service_state_to_archived_state(int current_status) {
if(current_status == SERVICE_OK)
return AS_SVC_OK;
if(current_status == SERVICE_UNKNOWN)
return AS_SVC_UNKNOWN;
if(current_status == SERVICE_WARNING)
return AS_SVC_WARNING;
if(current_status == SERVICE_CRITICAL)
return AS_SVC_CRITICAL;
return AS_NO_DATA;
}
/* adds an archived state entry */
void add_archived_state(int entry_type, int state_type, time_t time_stamp, char *state_info) {
archived_state *last_as = NULL;
archived_state *temp_as = NULL;
archived_state *new_as = NULL;
#ifdef DEBUG
printf("Added state %d @ %s", state_type, ctime(&time_stamp));
#endif
/* allocate memory for the new entry */
new_as = (archived_state *)malloc(sizeof(archived_state));
if(new_as == NULL)
return;
/* allocate memory fo the state info */
if(state_info != NULL) {
new_as->state_info = (char *)malloc(strlen(state_info) + 1);
if(new_as->state_info != NULL)
strcpy(new_as->state_info, state_info);
}
else new_as->state_info = NULL;
new_as->entry_type = entry_type;
new_as->processed_state = entry_type;
new_as->state_type = state_type;
new_as->time_stamp = time_stamp;
/* add the new entry to the list in memory, sorted by time */
last_as = as_list;
for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
if(new_as->time_stamp < temp_as->time_stamp) {
new_as->next = temp_as;
if(temp_as == as_list)
as_list = new_as;
else
last_as->next = new_as;
break;
}
else
last_as = temp_as;
}
if(as_list == NULL) {
new_as->next = NULL;
as_list = new_as;
}
else if(temp_as == NULL) {
new_as->next = NULL;
last_as->next = new_as;
}
return;
}
/* frees memory allocated to the archived state list */
void free_archived_state_list(void) {
archived_state *this_as = NULL;
archived_state *next_as = NULL;
for(this_as = as_list; this_as != NULL;) {
next_as = this_as->next;
if(this_as->state_info != NULL)
free(this_as->state_info);
free(this_as);
this_as = next_as;
}
as_list = NULL;
return;
}
/* reads log files for archived state data */
void read_archived_state_data(void) {
char filename[MAX_FILENAME_LENGTH];
int newest_archive = 0;
int oldest_archive = 0;
int current_archive;
#ifdef DEBUG
printf("Determining archives to use...\n");
#endif
/* determine earliest archive to use */
oldest_archive = determine_archive_to_use_from_time(t1);
if(log_rotation_method != LOG_ROTATION_NONE)
oldest_archive += backtrack_archives;
/* determine most recent archive to use */
newest_archive = determine_archive_to_use_from_time(t2);
if(oldest_archive < newest_archive)
oldest_archive = newest_archive;
#ifdef DEBUG
printf("Oldest archive: %d\n", oldest_archive);
printf("Newest archive: %d\n", newest_archive);
#endif
/* read in all the necessary archived logs */
for(current_archive = newest_archive; current_archive <= oldest_archive; current_archive++) {
/* 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("\tCurrent archive: %d (%s)\n", current_archive, filename);
#endif
/* scan the log file for archived state data */
scan_log_file_for_archived_state_data(filename);
}
return;
}
/* grabs archives state data from a log file */
void scan_log_file_for_archived_state_data(char *filename) {
char *input = NULL;
char *input2 = NULL;
char entry_host_name[MAX_INPUT_BUFFER];
char entry_svc_description[MAX_INPUT_BUFFER];
char *plugin_output = NULL;
char *temp_buffer = NULL;
time_t time_stamp;
mmapfile *thefile = NULL;
int state_type = 0;
/* print something so browser doesn't time out */
if(mode == CREATE_HTML) {
printf(" ");
fflush(NULL);
}
if((thefile = mmap_fopen(filename)) == NULL) {
#ifdef DEBUG
printf("Could not open file '%s' for reading.\n", filename);
#endif
return;
}
#ifdef DEBUG
printf("Scanning log file '%s' for archived state data...\n", filename);
#endif
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..."))
add_archived_state(AS_PROGRAM_START, AS_NO_DATA, time_stamp, "Program start");
if(strstr(input, " restarting..."))
add_archived_state(AS_PROGRAM_START, AS_NO_DATA, time_stamp, "Program restart");
/* program stops */
if(strstr(input, " shutting down..."))
add_archived_state(AS_PROGRAM_END, AS_NO_DATA, time_stamp, "Normal program termination");
if(strstr(input, "Bailing out"))
add_archived_state(AS_PROGRAM_END, AS_NO_DATA, time_stamp, "Abnormal program termination");
if(display_type == DISPLAY_HOST_TRENDS) {
if(strstr(input, "HOST ALERT:") || strstr(input, "INITIAL HOST STATE:") || strstr(input, "CURRENT HOST STATE:")) {
free(input2);
if((input2 = strdup(input)) == NULL)
continue;
/* get host name */
temp_buffer = my_strtok(input2, "]");
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';
if(strcmp(host_name, entry_host_name))
continue;
/* state types */
if(strstr(input, ";SOFT;")) {
if(include_soft_states == FALSE)
continue;
state_type = AS_SOFT_STATE;
}
if(strstr(input, ";HARD;"))
state_type = AS_HARD_STATE;
/* 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");
if(strstr(input, ";DOWN;"))
add_archived_state(AS_HOST_DOWN, state_type, time_stamp, plugin_output);
else if(strstr(input, ";UNREACHABLE;"))
add_archived_state(AS_HOST_UNREACHABLE, state_type, time_stamp, plugin_output);
else if(strstr(input, ";RECOVERY") || strstr(input, ";UP;"))
add_archived_state(AS_HOST_UP, state_type, time_stamp, plugin_output);
else
add_archived_state(AS_NO_DATA, AS_NO_DATA, time_stamp, plugin_output);
}
}
if(display_type == DISPLAY_SERVICE_TRENDS) {
if(strstr(input, "SERVICE ALERT:") || strstr(input, "INITIAL SERVICE STATE:") || strstr(input, "CURRENT SERVICE STATE:")) {
free(input2);
if((input2 = strdup(input)) == NULL)
continue;
/* get host name */
temp_buffer = my_strtok(input2, "]");
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';
if(strcmp(host_name, entry_host_name))
continue;
/* 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(strcmp(svc_description, entry_svc_description))
continue;
/* state types */
if(strstr(input, ";SOFT;")) {
if(include_soft_states == FALSE)
continue;
state_type = AS_SOFT_STATE;
}
if(strstr(input, ";HARD;"))
state_type = AS_HARD_STATE;
/* 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");
if(strstr(input, ";CRITICAL;"))
add_archived_state(AS_SVC_CRITICAL, state_type, time_stamp, plugin_output);
else if(strstr(input, ";WARNING;"))
add_archived_state(AS_SVC_WARNING, state_type, time_stamp, plugin_output);
else if(strstr(input, ";UNKNOWN;"))
add_archived_state(AS_SVC_UNKNOWN, state_type, time_stamp, plugin_output);
else if(strstr(input, ";RECOVERY;") || strstr(input, ";OK;"))
add_archived_state(AS_SVC_OK, state_type, time_stamp, plugin_output);
else
add_archived_state(AS_NO_DATA, AS_NO_DATA, time_stamp, plugin_output);
}
}
}
/* free memory and close the file */
free(input);
free(input2);
mmap_fclose(thefile);
return;
}
/* write JavaScript code and layer for popup window */
void write_popup_code(void) {
char *border_color = "#000000";
char *background_color = "#ffffcc";
int border = 1;
int padding = 3;
int x_offset = 3;
int y_offset = 3;
printf("\n");
return;
}
/* write timestamps */
void draw_timestamps(void) {
int last_timestamp = 0;
archived_state *temp_as;
double start_pixel_ratio;
int start_pixel;
if(mode != CREATE_IMAGE)
return;
/* draw first timestamp */
draw_timestamp(0, t1);
last_timestamp = 0;
for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
if(temp_as->time_stamp < t1 || temp_as->time_stamp > t2)
continue;
start_pixel_ratio = ((double)(temp_as->time_stamp - t1)) / ((double)(t2 - t1));
start_pixel = (int)(start_pixel_ratio * (drawing_width - 1));
/* draw start timestamp if possible */
if((start_pixel > last_timestamp + MIN_TIMESTAMP_SPACING) && (start_pixel < drawing_width - 1 - MIN_TIMESTAMP_SPACING)) {
draw_timestamp(start_pixel, temp_as->time_stamp);
last_timestamp = start_pixel;
}
}
/* draw last timestamp */
draw_timestamp(drawing_width - 1, t2);
return;
}
/* write timestamp below graph */
void draw_timestamp(int ts_pixel, time_t ts_time) {
char temp_buffer[MAX_INPUT_BUFFER];
int string_height;
int string_width;
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s", ctime(&ts_time));
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
temp_buffer[strlen(temp_buffer) - 1] = '\x0';
string_height = gdFontSmall->h;
string_width = gdFontSmall->w * strlen(temp_buffer);
if(small_image == FALSE)
gdImageStringUp(trends_image, gdFontSmall, ts_pixel + drawing_x_offset - (string_height / 2), drawing_y_offset + drawing_height + string_width + 5, (unsigned char *)temp_buffer, color_black);
/* draw a dashed vertical line at this point */
if(ts_pixel > 0 && ts_pixel < (drawing_width - 1))
draw_dashed_line(ts_pixel + drawing_x_offset, drawing_y_offset, ts_pixel + drawing_x_offset, drawing_y_offset + drawing_height, color_black);
return;
}
/* draw total state times */
void draw_time_breakdowns(void) {
char temp_buffer[MAX_INPUT_BUFFER];
unsigned long total_time = 0L;
unsigned long total_state_time;
unsigned long time_indeterminate = 0L;
int string_height;
if(mode == CREATE_HTML)
return;
if(small_image == TRUE)
return;
total_time = (unsigned long)(t2 - t1);
if(display_type == DISPLAY_HOST_TRENDS)
total_state_time = time_up + time_down + time_unreachable;
else
total_state_time = time_ok + time_warning + time_unknown + time_critical;
if(total_state_time >= total_time)
time_indeterminate = 0L;
else
time_indeterminate = total_time - total_state_time;
string_height = gdFontSmall->h;
if(display_type == DISPLAY_HOST_TRENDS) {
get_time_breakdown_string(total_time, time_up, "Up", &temp_buffer[0], sizeof(temp_buffer));
gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 5, (unsigned char *)temp_buffer, color_darkgreen);
gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 2), drawing_y_offset + 5, (unsigned char *)"Up", color_darkgreen);
get_time_breakdown_string(total_time, time_down, "Down", &temp_buffer[0], sizeof(temp_buffer));
gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 25, (unsigned char *)temp_buffer, color_red);
gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 4), drawing_y_offset + 25, (unsigned char *)"Down", color_red);
get_time_breakdown_string(total_time, time_unreachable, "Unreachable", &temp_buffer[0], sizeof(temp_buffer));
gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 45, (unsigned char *)temp_buffer, color_darkred);
gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 11), drawing_y_offset + 45, (unsigned char *)"Unreachable", color_darkred);
get_time_breakdown_string(total_time, time_indeterminate, "Indeterminate", &temp_buffer[0], sizeof(temp_buffer));
gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 65, (unsigned char *)temp_buffer, color_black);
gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 13), drawing_y_offset + 65, (unsigned char *)"Indeterminate", color_black);
}
else {
get_time_breakdown_string(total_time, time_ok, "Ok", &temp_buffer[0], sizeof(temp_buffer));
gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 5, (unsigned char *)temp_buffer, color_darkgreen);
gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 2), drawing_y_offset + 5, (unsigned char *)"Ok", color_darkgreen);
get_time_breakdown_string(total_time, time_warning, "Warning", &temp_buffer[0], sizeof(temp_buffer));
gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 25, (unsigned char *)temp_buffer, color_yellow);
gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 7), drawing_y_offset + 25, (unsigned char *)"Warning", color_yellow);
get_time_breakdown_string(total_time, time_unknown, "Unknown", &temp_buffer[0], sizeof(temp_buffer));
gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 45, (unsigned char *)temp_buffer, color_orange);
gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 7), drawing_y_offset + 45, (unsigned char *)"Unknown", color_orange);
get_time_breakdown_string(total_time, time_critical, "Critical", &temp_buffer[0], sizeof(temp_buffer));
gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 65, (unsigned char *)temp_buffer, color_red);
gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 8), drawing_y_offset + 65, (unsigned char *)"Critical", color_red);
get_time_breakdown_string(total_time, time_indeterminate, "Indeterminate", &temp_buffer[0], sizeof(temp_buffer));
gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 85, (unsigned char *)temp_buffer, color_black);
gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 13), drawing_y_offset + 85, (unsigned char *)"Indeterminate", color_black);
}
return;
}
void get_time_breakdown_string(unsigned long total_time, unsigned long state_time, char *state_string, char *buffer, int buffer_length) {
int days;
int hours;
int minutes;
int seconds;
double percent_time;
get_time_breakdown(state_time, &days, &hours, &minutes, &seconds);
if(total_time == 0L)
percent_time = 0.0;
else
percent_time = ((double)state_time / total_time) * 100.0;
snprintf(buffer, buffer_length - 1, "%-13s: (%.3f%%) %dd %dh %dm %ds", state_string, percent_time, days, hours, minutes, seconds);
buffer[buffer_length - 1] = '\x0';
return;
}
void convert_timeperiod_to_times(int type) {
time_t current_time;
struct tm *t;
/* get the current time */
time(¤t_time);
t = localtime(¤t_time);
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
t->tm_isdst = -1;
switch(type) {
case TIMEPERIOD_LAST24HOURS:
t1 = current_time - (60 * 60 * 24);
t2 = current_time;
break;
case TIMEPERIOD_TODAY:
t1 = mktime(t);
t2 = current_time;
break;
case TIMEPERIOD_YESTERDAY:
t1 = (time_t)(mktime(t) - (60 * 60 * 24));
t2 = (time_t)mktime(t);
break;
case TIMEPERIOD_THISWEEK:
t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
t2 = current_time;
break;
case TIMEPERIOD_LASTWEEK:
t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday) - (60 * 60 * 24 * 7));
t2 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
break;
case TIMEPERIOD_THISMONTH:
t->tm_mday = 1;
t1 = mktime(t);
t2 = current_time;
break;
case TIMEPERIOD_LASTMONTH:
t->tm_mday = 1;
t2 = mktime(t);
if(t->tm_mon == 0) {
t->tm_mon = 11;
t->tm_year--;
}
else
t->tm_mon--;
t1 = mktime(t);
break;
case TIMEPERIOD_THISQUARTER:
break;
case TIMEPERIOD_LASTQUARTER:
break;
case TIMEPERIOD_THISYEAR:
t->tm_mon = 0;
t->tm_mday = 1;
t1 = mktime(t);
t2 = current_time;
break;
case TIMEPERIOD_LASTYEAR:
t->tm_mon = 0;
t->tm_mday = 1;
t2 = mktime(t);
t->tm_year--;
t1 = mktime(t);
break;
case TIMEPERIOD_NEXTPROBLEM:
/* Time period will be defined later */
break;
case TIMEPERIOD_LAST7DAYS:
t2 = current_time;
t1 = current_time - (7 * 24 * 60 * 60);
break;
case TIMEPERIOD_LAST31DAYS:
t2 = current_time;
t1 = current_time - (31 * 24 * 60 * 60);
break;
default:
break;
}
return;
}
void compute_report_times(void) {
time_t current_time;
struct tm *st;
struct tm *et;
/* get the current time */
time(¤t_time);
st = localtime(¤t_time);
st->tm_sec = start_second;
st->tm_min = start_minute;
st->tm_hour = start_hour;
st->tm_mday = start_day;
st->tm_mon = start_month - 1;
st->tm_year = start_year - 1900;
st->tm_isdst = -1;
t1 = mktime(st);
et = localtime(¤t_time);
et->tm_sec = end_second;
et->tm_min = end_minute;
et->tm_hour = end_hour;
et->tm_mday = end_day;
et->tm_mon = end_month - 1;
et->tm_year = end_year - 1900;
et->tm_isdst = -1;
t2 = mktime(et);
}
/* draws a dashed line */
void draw_dashed_line(int x1, int y1, int x2, int y2, int color) {
int styleDashed[12];
styleDashed[0] = color;
styleDashed[1] = color;
styleDashed[2] = gdTransparent;
styleDashed[3] = gdTransparent;
styleDashed[4] = color;
styleDashed[5] = color;
styleDashed[6] = gdTransparent;
styleDashed[7] = gdTransparent;
styleDashed[8] = color;
styleDashed[9] = color;
styleDashed[10] = gdTransparent;
styleDashed[11] = gdTransparent;
/* sets current style to a dashed line */
gdImageSetStyle(trends_image, styleDashed, 12);
/* draws a line (dashed) */
gdImageLine(trends_image, x1, y1, x2, y2, gdStyled);
return;
}
/* draws horizontal grid lines */
void draw_horizontal_grid_lines(void) {
if(mode == CREATE_HTML)
return;
if(small_image == TRUE)
return;
draw_dashed_line(drawing_x_offset, drawing_y_offset + 10, drawing_x_offset + drawing_width, drawing_y_offset + 10, color_black);
draw_dashed_line(drawing_x_offset, drawing_y_offset + 30, drawing_x_offset + drawing_width, drawing_y_offset + 30, color_black);
draw_dashed_line(drawing_x_offset, drawing_y_offset + 50, drawing_x_offset + drawing_width, drawing_y_offset + 50, color_black);
if(display_type == DISPLAY_SERVICE_TRENDS)
draw_dashed_line(drawing_x_offset, drawing_y_offset + 70, drawing_x_offset + drawing_width, drawing_y_offset + 70, color_black);
return;
}
nagios/common/ 0000775 0000000 0000000 00000000000 12210155146 0013623 5 ustar 00root root 0000000 0000000 nagios/common/.gitignore 0000664 0000000 0000000 00000000011 12210155146 0015603 0 ustar 00root root 0000000 0000000 Makefile
nagios/common/Makefile.in 0000664 0000000 0000000 00000001051 12210155146 0015665 0 ustar 00root root 0000000 0000000 ############################
# Makefile for Nagios
#
# Last Modified: 04-08-2003
############################
# Source code directories
SRC_BASE=../common
SRC_CGI=../cgi
CC=@CC@
CFLAGS=@CFLAGS@ @DEFS@
LDFLAGS=@LDFLAGS@ @LIBS@
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
CGIDIR=@sbindir@
HTMLDIR=@datarootdir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
COMMAND_OPTS=@COMMAND_OPTS@
CP=@CP@
clean:
rm -f core *.o
rm -f *~
distclean: clean
rm -f Makefile
devclean: distclean
install:
nagios/common/comments.c 0000664 0000000 0000000 00000053751 12210155146 0015627 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* COMMENTS.C - Comment functions for Nagios
*
* Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 08-28-2010
*
* 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/comments.h"
#include "../include/objects.h"
/***** IMPLEMENTATION-SPECIFIC INCLUDES *****/
#ifdef USE_XCDDEFAULT
#include "../xdata/xcddefault.h"
#endif
#ifdef NSCORE
#include "../include/nagios.h"
#include "../include/broker.h"
#endif
#ifdef NSCGI
#include "../include/cgiutils.h"
#endif
comment *comment_list = NULL;
int defer_comment_sorting = 0;
comment **comment_hashlist = NULL;
#ifdef NSCORE
pthread_mutex_t nagios_comment_lock = PTHREAD_MUTEX_INITIALIZER;
/******************************************************************/
/**************** INITIALIZATION/CLEANUP FUNCTIONS ****************/
/******************************************************************/
/* 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;
}
/* 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 **********************/
/******************************************************************/
/* 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;
unsigned long new_comment_id = 0L;
if(type == HOST_COMMENT)
result = add_new_host_comment(entry_type, host_name, entry_time, author_name, comment_data, persistent, source, expires, expire_time, &new_comment_id);
else
result = add_new_service_comment(entry_type, host_name, svc_description, entry_time, author_name, comment_data, persistent, source, expires, expire_time, &new_comment_id);
/* add an event to expire comment data if necessary... */
if(expires == TRUE)
schedule_new_event(EVENT_EXPIRE_COMMENT, FALSE, expire_time, FALSE, 0, NULL, TRUE, (void *)new_comment_id, NULL, 0);
/* save comment id */
if(comment_id != NULL)
*comment_id = new_comment_id;
return result;
}
/* 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;
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)
*comment_id = new_comment_id;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_comment_data(NEBTYPE_COMMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, HOST_COMMENT, entry_type, host_name, NULL, entry_time, author_name, comment_data, persistent, source, expires, expire_time, new_comment_id, NULL);
#endif
return result;
}
/* 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;
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)
*comment_id = new_comment_id;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_comment_data(NEBTYPE_COMMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_COMMENT, entry_type, host_name, svc_description, entry_time, author_name, comment_data, persistent, source, expires, expire_time, new_comment_id, NULL);
#endif
return result;
}
/******************************************************************/
/***************** COMMENT DELETION FUNCTIONS *********************/
/******************************************************************/
/* 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;
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
/* find the comment we should remove */
for(this_comment = comment_list, last_comment = comment_list; this_comment != NULL; this_comment = next_comment) {
next_comment = this_comment->next;
/* we found the comment we should delete */
if(this_comment->comment_id == comment_id && this_comment->comment_type == type)
break;
last_comment = this_comment;
}
/* 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);
#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;
}
last_hash = this_hash;
}
/* 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;
}
else
result = ERROR;
/**** 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
#ifdef NSCORE
pthread_mutex_unlock(&nagios_comment_lock);
#endif
return result;
}
/* deletes a host comment */
int delete_host_comment(unsigned long comment_id) {
int result = OK;
/* delete the comment from memory */
result = delete_comment(HOST_COMMENT, comment_id);
return result;
}
/* deletes a service comment */
int delete_service_comment(unsigned long comment_id) {
int result = OK;
/* delete the comment from memory */
result = delete_comment(SERVICE_COMMENT, comment_id);
return result;
}
/* deletes all comments for a particular host or service */
int delete_all_comments(int type, char *host_name, char *svc_description) {
int result = OK;
if(type == HOST_COMMENT)
result = delete_all_host_comments(host_name);
else
result = delete_all_service_comments(host_name, svc_description);
return result;
}
/* 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;
if(host_name == NULL)
return ERROR;
/* delete host comments from memory */
for(temp_comment = get_first_comment_by_host(host_name); temp_comment != NULL; temp_comment = next_comment) {
next_comment = get_next_comment_by_host(host_name, temp_comment);
if(temp_comment->comment_type == HOST_COMMENT)
delete_comment(HOST_COMMENT, temp_comment->comment_id);
}
return result;
}
/* 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;
if(hst == NULL)
return ERROR;
/* delete comments from memory */
temp_comment = get_first_comment_by_host(hst->name);
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);
}
temp_comment = next_comment;
}
return result;
}
/* 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;
if(host_name == NULL || svc_description == NULL)
return ERROR;
/* delete service comments from memory */
for(temp_comment = comment_list; temp_comment != NULL; temp_comment = next_comment) {
next_comment = temp_comment->next;
if(temp_comment->comment_type == SERVICE_COMMENT && !strcmp(temp_comment->host_name, host_name) && !strcmp(temp_comment->service_description, svc_description))
delete_comment(SERVICE_COMMENT, temp_comment->comment_id);
}
return result;
}
/* 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;
if(svc == NULL)
return ERROR;
/* delete comments from memory */
for(temp_comment = comment_list; temp_comment != NULL; temp_comment = next_comment) {
next_comment = temp_comment->next;
if(temp_comment->comment_type == SERVICE_COMMENT && !strcmp(temp_comment->host_name, svc->host_name) && !strcmp(temp_comment->service_description, svc->description) && temp_comment->entry_type == ACKNOWLEDGEMENT_COMMENT && temp_comment->persistent == FALSE)
delete_comment(SERVICE_COMMENT, temp_comment->comment_id);
}
return result;
}
/* checks for an expired comment (and removes it) */
int check_for_expired_comment(unsigned long comment_id) {
comment *temp_comment = NULL;
/* check all comments */
for(temp_comment = comment_list; temp_comment != NULL; temp_comment = temp_comment->next) {
/* delete the now expired comment */
if(temp_comment->comment_id == comment_id && temp_comment->expires == TRUE && temp_comment->expire_time < time(NULL)) {
delete_comment(temp_comment->comment_type, comment_id);
break;
}
}
return OK;
}
#endif
/******************************************************************/
/****************** CHAINED HASH FUNCTIONS ************************/
/******************************************************************/
/* adds comment to hash list in memory */
int add_comment_to_hashlist(comment *new_comment) {
comment *temp_comment = NULL;
comment *lastpointer = NULL;
int hashslot = 0;
/* initialize hash list */
if(comment_hashlist == NULL) {
int i;
comment_hashlist = (comment **)malloc(sizeof(comment *) * COMMENT_HASHSLOTS);
if(comment_hashlist == NULL)
return 0;
for(i = 0; i < COMMENT_HASHSLOTS; i++)
comment_hashlist[i] = NULL;
}
if(!new_comment)
return 0;
hashslot = hashfunc(new_comment->host_name, NULL, COMMENT_HASHSLOTS);
lastpointer = NULL;
for(temp_comment = comment_hashlist[hashslot]; temp_comment && compare_hashdata(temp_comment->host_name, NULL, new_comment->host_name, NULL) < 0; temp_comment = temp_comment->nexthash) {
if(compare_hashdata(temp_comment->host_name, NULL, new_comment->host_name, NULL) >= 0)
break;
lastpointer = temp_comment;
}
/* multiples are allowed */
if(lastpointer)
lastpointer->nexthash = new_comment;
else
comment_hashlist[hashslot] = new_comment;
new_comment->nexthash = temp_comment;
return 1;
}
/******************************************************************/
/******************** ADDITION FUNCTIONS **************************/
/******************************************************************/
/* adds a host comment to the list in memory */
int add_host_comment(int entry_type, char *host_name, time_t entry_time, char *author, char *comment_data, unsigned long comment_id, int persistent, int expires, time_t expire_time, int source) {
int result = OK;
result = add_comment(HOST_COMMENT, entry_type, host_name, NULL, entry_time, author, comment_data, comment_id, persistent, expires, expire_time, source);
return result;
}
/* adds a service comment to the list in memory */
int add_service_comment(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) {
int result = OK;
result = add_comment(SERVICE_COMMENT, entry_type, host_name, svc_description, entry_time, author, comment_data, comment_id, persistent, expires, expire_time, source);
return result;
}
/* 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;
int result = OK;
/* make sure we have the data we need */
if(host_name == NULL || author == NULL || comment_data == NULL || (comment_type == SERVICE_COMMENT && svc_description == NULL))
return ERROR;
/* allocate memory for the comment */
if((new_comment = (comment *)calloc(1, sizeof(comment))) == NULL)
return ERROR;
/* duplicate vars */
if((new_comment->host_name = (char *)strdup(host_name)) == NULL)
result = ERROR;
if(comment_type == SERVICE_COMMENT) {
if((new_comment->service_description = (char *)strdup(svc_description)) == NULL)
result = ERROR;
}
if((new_comment->author = (char *)strdup(author)) == NULL)
result = ERROR;
if((new_comment->comment_data = (char *)strdup(comment_data)) == NULL)
result = ERROR;
new_comment->comment_type = comment_type;
new_comment->entry_type = entry_type;
new_comment->source = source;
new_comment->entry_time = entry_time;
new_comment->comment_id = comment_id;
new_comment->persistent = (persistent == TRUE) ? TRUE : FALSE;
new_comment->expires = (expires == TRUE) ? TRUE : FALSE;
new_comment->expire_time = expire_time;
/* add comment to hash list */
if(result == OK) {
if(!add_comment_to_hashlist(new_comment))
result = ERROR;
}
/* handle errors */
if(result == ERROR) {
my_free(new_comment->comment_data);
my_free(new_comment->author);
my_free(new_comment->service_description);
my_free(new_comment->host_name);
my_free(new_comment);
return ERROR;
}
if(defer_comment_sorting) {
new_comment->next = comment_list;
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
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) {
new_comment->next = temp_comment;
if(temp_comment == comment_list)
comment_list = new_comment;
else
last_comment->next = new_comment;
break;
}
else
last_comment = temp_comment;
}
if(comment_list == NULL) {
new_comment->next = NULL;
comment_list = new_comment;
}
else if(temp_comment == NULL) {
new_comment->next = NULL;
last_comment->next = new_comment;
}
#ifdef NSCORE
pthread_mutex_unlock(&nagios_comment_lock);
#endif
}
#ifdef NSCORE
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_comment_data(NEBTYPE_COMMENT_LOAD, NEBFLAG_NONE, NEBATTR_NONE, comment_type, entry_type, host_name, svc_description, entry_time, author, comment_data, persistent, source, expires, expire_time, comment_id, NULL);
#endif
#endif
return OK;
}
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);
}
int sort_comments(void) {
comment **array, *temp_comment;
unsigned long i = 0, unsorted_comments = 0;
if(!defer_comment_sorting)
return OK;
defer_comment_sorting = 0;
temp_comment = comment_list;
while(temp_comment != NULL) {
temp_comment = temp_comment->next;
unsorted_comments++;
}
if(!unsorted_comments)
return OK;
if(!(array = malloc(sizeof(*array) * unsorted_comments)))
return ERROR;
while(comment_list) {
array[i++] = comment_list;
comment_list = comment_list->next;
}
qsort((void *)array, i, sizeof(*array), comment_compar);
comment_list = temp_comment = array[0];
for(i = 1; i < unsorted_comments; i++) {
temp_comment->next = array[i];
temp_comment = temp_comment->next;
}
temp_comment->next = NULL;
my_free(array);
return OK;
}
/******************************************************************/
/********************* CLEANUP FUNCTIONS **************************/
/******************************************************************/
/* frees memory allocated for the comment data */
void free_comment_data(void) {
comment *this_comment = NULL;
comment *next_comment = NULL;
/* free memory for the comment list */
for(this_comment = comment_list; this_comment != NULL; this_comment = next_comment) {
next_comment = this_comment->next;
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);
}
/* free hash list and reset list pointer */
my_free(comment_hashlist);
comment_hashlist = NULL;
comment_list = NULL;
return;
}
/******************************************************************/
/********************* UTILITY FUNCTIONS **************************/
/******************************************************************/
/* get the number of comments associated with a particular host */
int number_of_host_comments(char *host_name) {
comment *temp_comment = NULL;
int total_comments = 0;
if(host_name == NULL)
return 0;
for(temp_comment = get_first_comment_by_host(host_name); temp_comment != NULL; temp_comment = get_next_comment_by_host(host_name, temp_comment)) {
if(temp_comment->comment_type == HOST_COMMENT)
total_comments++;
}
return total_comments;
}
/* 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;
int total_comments = 0;
if(host_name == NULL || svc_description == NULL)
return 0;
for(temp_comment = get_first_comment_by_host(host_name); temp_comment != NULL; temp_comment = get_next_comment_by_host(host_name, temp_comment)) {
if(temp_comment->comment_type == SERVICE_COMMENT && !strcmp(temp_comment->service_description, svc_description))
total_comments++;
}
return total_comments;
}
/******************************************************************/
/********************* TRAVERSAL FUNCTIONS ************************/
/******************************************************************/
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;
if(host_name == NULL || comment_hashlist == NULL)
return NULL;
if(start == NULL)
temp_comment = comment_hashlist[hashfunc(host_name, NULL, COMMENT_HASHSLOTS)];
else
temp_comment = start->nexthash;
for(; temp_comment && compare_hashdata(temp_comment->host_name, NULL, host_name, NULL) < 0; temp_comment = temp_comment->nexthash);
if(temp_comment && compare_hashdata(temp_comment->host_name, NULL, host_name, NULL) == 0)
return temp_comment;
return NULL;
}
/******************************************************************/
/********************** SEARCH FUNCTIONS **************************/
/******************************************************************/
/* find a service comment by id */
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) {
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;
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)
return temp_comment;
}
return NULL;
}
nagios/common/downtime.c 0000664 0000000 0000000 00000132517 12210155146 0015626 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* DOWNTIME.C - Scheduled downtime functions for Nagios
*
* Copyright (c) 2000-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 02-17-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.
*
*****************************************************************************/
#include "../include/config.h"
#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"
#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
#ifdef NSCORE
/******************************************************************/
/**************** INITIALIZATION/CLEANUP FUNCTIONS ****************/
/******************************************************************/
/* initializes scheduled downtime data */
int initialize_downtime_data(char *config_file) {
int result = OK;
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;
}
/* 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
/* free memory allocated to downtime data */
free_downtime_data();
return result;
}
/******************************************************************/
/********************** SCHEDULING FUNCTIONS **********************/
/******************************************************************/
/* schedules a host or service downtime */
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) {
unsigned long downtime_id = 0L;
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);
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);
/* register the scheduled downtime */
register_downtime(type, downtime_id);
/* return downtime id */
if(new_downtime_id != NULL)
*new_downtime_id = downtime_id;
return OK;
}
/* unschedules a host or service downtime */
int unschedule_downtime(int type, unsigned long downtime_id) {
scheduled_downtime *temp_downtime = NULL;
scheduled_downtime *next_downtime = NULL;
host *hst = NULL;
service *svc = NULL;
timed_event *temp_event = NULL;
#ifdef USE_EVENT_BROKER
int attr = 0;
#endif
log_debug_info(DEBUGL_FUNCTIONS, 0, "unschedule_downtime()\n");
/* find the downtime entry in the list in memory */
if((temp_downtime = find_downtime(type, downtime_id)) == NULL)
return ERROR;
/* find the host or service associated with this downtime */
if(temp_downtime->type == HOST_DOWNTIME) {
if((hst = find_host(temp_downtime->host_name)) == NULL)
return ERROR;
}
else {
if((svc = find_service(temp_downtime->host_name, temp_downtime->service_description)) == NULL)
return ERROR;
}
/* decrement pending flex downtime if necessary ... */
if(temp_downtime->fixed == FALSE && temp_downtime->incremented_pending_downtime == TRUE) {
if(temp_downtime->type == HOST_DOWNTIME)
hst->pending_flex_downtime--;
else
svc->pending_flex_downtime--;
}
/* decrement the downtime depth variable and update status data if necessary */
if(temp_downtime->is_in_effect == TRUE) {
#ifdef USE_EVENT_BROKER
/* send data to event broker */
attr = NEBATTR_DOWNTIME_STOP_CANCELLED;
broker_downtime_data(NEBTYPE_DOWNTIME_STOP, NEBFLAG_NONE, attr, temp_downtime->type, temp_downtime->host_name, temp_downtime->service_description, temp_downtime->entry_time, temp_downtime->author, temp_downtime->comment, temp_downtime->start_time, temp_downtime->end_time, temp_downtime->fixed, temp_downtime->triggered_by, temp_downtime->duration, temp_downtime->downtime_id, NULL);
#endif
if(temp_downtime->type == HOST_DOWNTIME) {
hst->scheduled_downtime_depth--;
update_host_status(hst, FALSE);
/* log a notice - this is parsed by the history CGI */
if(hst->scheduled_downtime_depth == 0) {
logit(NSLOG_INFO_MESSAGE, FALSE, "HOST DOWNTIME ALERT: %s;CANCELLED; Scheduled downtime for host has been cancelled.\n", hst->name);
/* send a notification */
host_notification(hst, NOTIFICATION_DOWNTIMECANCELLED, NULL, NULL, NOTIFICATION_OPTION_NONE);
}
}
else {
svc->scheduled_downtime_depth--;
update_service_status(svc, FALSE);
/* log a notice - this is parsed by the history CGI */
if(svc->scheduled_downtime_depth == 0) {
logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE DOWNTIME ALERT: %s;%s;CANCELLED; Scheduled downtime for service has been cancelled.\n", svc->host_name, svc->description);
/* send a notification */
service_notification(svc, NOTIFICATION_DOWNTIMECANCELLED, NULL, NULL, NOTIFICATION_OPTION_NONE);
}
}
}
/* 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;
}
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);
}
/* delete downtime entry */
if(temp_downtime->type == HOST_DOWNTIME)
delete_host_downtime(downtime_id);
else
delete_service_downtime(downtime_id);
/* unschedule all downtime entries that were triggered by this one */
while(1) {
for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = next_downtime) {
next_downtime = temp_downtime->next;
if(temp_downtime->triggered_by == downtime_id) {
unschedule_downtime(ANY_DOWNTIME, temp_downtime->downtime_id);
break;
}
}
if(temp_downtime == NULL)
break;
}
return OK;
}
/* registers scheduled downtime (schedules it, adds comments, etc.) */
int register_downtime(int type, unsigned long downtime_id) {
char *temp_buffer = NULL;
char start_time_string[MAX_DATETIME_LENGTH] = "";
char flex_start_string[MAX_DATETIME_LENGTH] = "";
char end_time_string[MAX_DATETIME_LENGTH] = "";
scheduled_downtime *temp_downtime = NULL;
host *hst = NULL;
service *svc = NULL;
char *type_string = NULL;
int hours = 0;
int minutes = 0;
int seconds = 0;
unsigned long *new_downtime_id = NULL;
int was_in_effect = FALSE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "register_downtime( %d, %lu)\n", type,
downtime_id);
/* find the downtime entry in memory */
temp_downtime = find_downtime(type, downtime_id);
if(temp_downtime == NULL) {
log_debug_info(DEBUGL_DOWNTIME, 0, "Cannot find downtime ID: %lu\n", downtime_id);
return ERROR;
}
/* 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,
"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);
return ERROR;
}
}
/* create the comment */
get_datetime_string(&(temp_downtime->start_time), start_time_string, MAX_DATETIME_LENGTH, SHORT_DATE_TIME);
get_datetime_string(&(temp_downtime->flex_downtime_start), flex_start_string, MAX_DATETIME_LENGTH, SHORT_DATE_TIME);
get_datetime_string(&(temp_downtime->end_time), end_time_string, MAX_DATETIME_LENGTH, SHORT_DATE_TIME);
hours = temp_downtime->duration / 3600;
minutes = ((temp_downtime->duration - (hours * 3600)) / 60);
seconds = temp_downtime->duration - (hours * 3600) - (minutes * 60);
if(temp_downtime->type == HOST_DOWNTIME)
type_string = "host";
else
type_string = "service";
if(temp_downtime->fixed == TRUE)
asprintf(&temp_buffer, "This %s has been scheduled for fixed downtime from %s to %s. Notifications for the %s will not be sent out during that time period.", type_string, start_time_string, end_time_string, type_string);
else
asprintf(&temp_buffer, "This %s has been scheduled for flexible downtime starting between %s and %s and lasting for a period of %d hours and %d minutes. Notifications for the %s will not be sent out during that time period.", type_string, start_time_string, end_time_string, hours, minutes, type_string);
log_debug_info(DEBUGL_DOWNTIME, 0, "Scheduled Downtime Details:\n");
if(temp_downtime->type == HOST_DOWNTIME) {
log_debug_info(DEBUGL_DOWNTIME, 0, " Type: Host Downtime\n");
log_debug_info(DEBUGL_DOWNTIME, 0, " Host: %s\n", hst->name);
}
else {
log_debug_info(DEBUGL_DOWNTIME, 0, " Type: Service Downtime\n");
log_debug_info(DEBUGL_DOWNTIME, 0, " Host: %s\n", svc->host_name);
log_debug_info(DEBUGL_DOWNTIME, 0, " Service: %s\n", svc->description);
}
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) {
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);
log_debug_info(DEBUGL_DOWNTIME, 0, " Duration: %dh %dm %ds\n", hours, minutes, seconds);
log_debug_info(DEBUGL_DOWNTIME, 0, " Downtime ID: %lu\n", temp_downtime->downtime_id);
log_debug_info(DEBUGL_DOWNTIME, 0, " Trigger ID: %lu\n", temp_downtime->triggered_by);
/* add a non-persistent comment to the host or service regarding the scheduled outage */
if(temp_downtime->type == SERVICE_DOWNTIME)
add_new_comment(SERVICE_COMMENT, DOWNTIME_COMMENT, svc->host_name, svc->description, time(NULL), ( NULL == temp_downtime->author ? "(Nagios Process)" : temp_downtime->author), temp_buffer, 0, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, &(temp_downtime->comment_id));
else
add_new_comment(HOST_COMMENT, DOWNTIME_COMMENT, hst->name, NULL, time(NULL), ( NULL == temp_downtime->author ? "(Nagios Process)" : temp_downtime->author), temp_buffer, 0, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, &(temp_downtime->comment_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)))) {
/* 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
downtime is already in effect, this means that we are restarting
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
another downtime event which will end the downtime. */
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);
/* Turn off is_in_effect flag so handle_scheduled_downtime() will
handle it correctly */
was_in_effect = temp_downtime->is_in_effect;
temp_downtime->is_in_effect = FALSE;
}
}
/* If the downtime is triggered and was in effect, mark it as not in
effect so it gets scheduled correctly */
if((temp_downtime->triggered_by != 0) &&
(TRUE == temp_downtime->is_in_effect)) {
was_in_effect = temp_downtime->is_in_effect;
temp_downtime->is_in_effect = FALSE;
}
if((FALSE == temp_downtime->fixed) && (FALSE == was_in_effect)) {
/* increment pending flex downtime counter */
if(temp_downtime->type == HOST_DOWNTIME)
hst->pending_flex_downtime++;
else
svc->pending_flex_downtime++;
temp_downtime->incremented_pending_downtime = TRUE;
/* Since a flex downtime may never start, schedule an expiring event in
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);
}
#ifdef PROBABLY_NOT_NEEDED
/*** FLEXIBLE DOWNTIME SANITY CHECK - ADDED 02/17/2008 ****/
/* if host/service is in a non-OK/UP state right now, see if we should start flexible time immediately */
/* this is new logic added in 3.0rc3 */
if(temp_downtime->fixed == FALSE) {
if(temp_downtime->type == HOST_DOWNTIME)
check_pending_flex_host_downtime(hst);
else
check_pending_flex_service_downtime(svc);
}
#endif
return OK;
}
/* handles scheduled downtime (id passed from timed event queue) */
int handle_scheduled_downtime_by_id(unsigned long downtime_id) {
scheduled_downtime *temp_downtime = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_scheduled_downtime_by_id()\n");
/* 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);
return ERROR;
}
/* handle the downtime */
return handle_scheduled_downtime(temp_downtime);
}
/* handles scheduled host or service downtime */
int handle_scheduled_downtime(scheduled_downtime *temp_downtime) {
scheduled_downtime *this_downtime = NULL;
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;
#endif
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_scheduled_downtime()\n");
if(temp_downtime == NULL)
return ERROR;
/* 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;
}
}
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;
}
}
/* have we come to the end of the scheduled downtime? */
if(temp_downtime->is_in_effect == TRUE) {
#ifdef USE_EVENT_BROKER
/* send data to event broker */
attr = NEBATTR_DOWNTIME_STOP_NORMAL;
broker_downtime_data(NEBTYPE_DOWNTIME_STOP, NEBFLAG_NONE, attr, temp_downtime->type, temp_downtime->host_name, temp_downtime->service_description, temp_downtime->entry_time, temp_downtime->author, temp_downtime->comment, temp_downtime->start_time, temp_downtime->end_time, temp_downtime->fixed, temp_downtime->triggered_by, temp_downtime->duration, temp_downtime->downtime_id, NULL);
#endif
/* decrement the downtime depth variable */
if(temp_downtime->type == HOST_DOWNTIME)
hst->scheduled_downtime_depth--;
else
svc->scheduled_downtime_depth--;
if(temp_downtime->type == HOST_DOWNTIME && hst->scheduled_downtime_depth == 0) {
log_debug_info(DEBUGL_DOWNTIME, 0, "Host '%s' has exited from a period of scheduled downtime (id=%lu).\n", hst->name, temp_downtime->downtime_id);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "HOST DOWNTIME ALERT: %s;STOPPED; Host has exited from a period of scheduled downtime", hst->name);
/* send a notification */
host_notification(hst, NOTIFICATION_DOWNTIMEEND, temp_downtime->author, temp_downtime->comment, NOTIFICATION_OPTION_NONE);
}
else if(temp_downtime->type == SERVICE_DOWNTIME && svc->scheduled_downtime_depth == 0) {
log_debug_info(DEBUGL_DOWNTIME, 0, "Service '%s' on host '%s' has exited from a period of scheduled downtime (id=%lu).\n", svc->description, svc->host_name, temp_downtime->downtime_id);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE DOWNTIME ALERT: %s;%s;STOPPED; Service has exited from a period of scheduled downtime", svc->host_name, svc->description);
/* send a notification */
service_notification(svc, NOTIFICATION_DOWNTIMEEND, temp_downtime->author, temp_downtime->comment, NOTIFICATION_OPTION_NONE);
}
/* update the status data */
if(temp_downtime->type == HOST_DOWNTIME)
update_host_status(hst, FALSE);
else
update_service_status(svc, FALSE);
/* decrement pending flex downtime if necessary */
if(temp_downtime->fixed == FALSE && temp_downtime->incremented_pending_downtime == TRUE) {
if(temp_downtime->type == HOST_DOWNTIME) {
if(hst->pending_flex_downtime > 0)
hst->pending_flex_downtime--;
}
else {
if(svc->pending_flex_downtime > 0)
svc->pending_flex_downtime--;
}
}
/* handle (stop) downtime that is triggered by this one */
while(1) {
/* list contents might change by recursive calls, so we use this inefficient method to prevent segfaults */
for(this_downtime = scheduled_downtime_list; this_downtime != NULL; this_downtime = this_downtime->next) {
if(this_downtime->triggered_by == temp_downtime->downtime_id) {
handle_scheduled_downtime(this_downtime);
break;
}
}
if(this_downtime == NULL)
break;
}
/* delete downtime entry */
if(temp_downtime->type == HOST_DOWNTIME)
delete_host_downtime(temp_downtime->downtime_id);
else
delete_service_downtime(temp_downtime->downtime_id);
}
/* else we are just starting the scheduled downtime */
else {
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_downtime_data(NEBTYPE_DOWNTIME_START, NEBFLAG_NONE, NEBATTR_NONE, temp_downtime->type, temp_downtime->host_name, temp_downtime->service_description, temp_downtime->entry_time, temp_downtime->author, temp_downtime->comment, temp_downtime->start_time, temp_downtime->end_time, temp_downtime->fixed, temp_downtime->triggered_by, temp_downtime->duration, temp_downtime->downtime_id, NULL);
#endif
if(temp_downtime->type == HOST_DOWNTIME && hst->scheduled_downtime_depth == 0) {
log_debug_info(DEBUGL_DOWNTIME, 0, "Host '%s' has entered a period of scheduled downtime (id=%lu).\n", hst->name, temp_downtime->downtime_id);
/* log a notice - this one is parsed by the history CGI */
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) {
host_notification(hst, NOTIFICATION_DOWNTIMESTART, temp_downtime->author, temp_downtime->comment, NOTIFICATION_OPTION_NONE);
temp_downtime->start_notification_sent = TRUE;
}
}
else if(temp_downtime->type == SERVICE_DOWNTIME && svc->scheduled_downtime_depth == 0) {
log_debug_info(DEBUGL_DOWNTIME, 0, "Service '%s' on host '%s' has entered a period of scheduled downtime (id=%lu).\n", svc->description, svc->host_name, temp_downtime->downtime_id);
/* log a notice - this one is parsed by the history CGI */
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) {
service_notification(svc, NOTIFICATION_DOWNTIMESTART, temp_downtime->author, temp_downtime->comment, NOTIFICATION_OPTION_NONE);
temp_downtime->start_notification_sent = TRUE;
}
}
/* increment the downtime depth variable */
if(temp_downtime->type == HOST_DOWNTIME)
hst->scheduled_downtime_depth++;
else
svc->scheduled_downtime_depth++;
/* set the in effect flag */
temp_downtime->is_in_effect = TRUE;
/* update the status data */
if(temp_downtime->type == HOST_DOWNTIME)
update_host_status(hst, FALSE);
else
update_service_status(svc, FALSE);
/* 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);
}
else {
event_time = temp_downtime->end_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, event_time, FALSE, 0, NULL, FALSE, (void *)new_downtime_id, NULL, 0);
}
/* handle (start) downtime that is triggered by this one */
for(this_downtime = scheduled_downtime_list; this_downtime != NULL; this_downtime = this_downtime->next) {
if(this_downtime->triggered_by == temp_downtime->downtime_id)
handle_scheduled_downtime(this_downtime);
}
}
return OK;
}
/* checks for flexible (non-fixed) host downtime that should start now */
int check_pending_flex_host_downtime(host *hst) {
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_host_downtime()\n");
if(hst == NULL)
return ERROR;
time(¤t_time);
/* if host is currently up, nothing to do */
if(hst->current_state == HOST_UP)
return OK;
/* 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) == hst) {
/* if the time boundaries are okay, start this scheduled downtime */
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 *)))) {
*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);
}
}
}
}
return OK;
}
/* checks for flexible (non-fixed) service downtime that should start now */
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");
if(svc == NULL)
return ERROR;
time(¤t_time);
/* if service is currently ok, nothing to do */
if(svc->current_state == STATE_OK)
return OK;
/* 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) == svc) {
/* if the time boundaries are okay, start this scheduled downtime */
if(temp_downtime->start_time <= current_time && current_time <= temp_downtime->end_time) {
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);
}
}
}
}
return OK;
}
/* 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;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_expired_downtime()\n");
time(¤t_time);
/* check all downtime entries... */
for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = next_downtime) {
next_downtime = temp_downtime->next;
/* this entry should be removed */
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);
/* delete the downtime entry */
if(temp_downtime->type == HOST_DOWNTIME)
delete_host_downtime(temp_downtime->downtime_id);
else
delete_service_downtime(temp_downtime->downtime_id);
}
}
return OK;
}
/******************************************************************/
/************************* SAVE FUNCTIONS *************************/
/******************************************************************/
/* 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 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);
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 result;
}
/* 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 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
/* save downtime id */
if(downtime_id != NULL)
*downtime_id = new_downtime_id;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_downtime_data(NEBTYPE_DOWNTIME_ADD, NEBFLAG_NONE, NEBATTR_NONE, HOST_DOWNTIME, host_name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, new_downtime_id, NULL);
#endif
return result;
}
/* 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 result = OK;
unsigned long new_downtime_id = 0L;
if(host_name == NULL || service_description == NULL)
return ERROR;
/**** 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
/* save downtime id */
if(downtime_id != NULL)
*downtime_id = new_downtime_id;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_downtime_data(NEBTYPE_DOWNTIME_ADD, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_DOWNTIME, host_name, service_description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, new_downtime_id, NULL);
#endif
return result;
}
/******************************************************************/
/*********************** DELETION FUNCTIONS ***********************/
/******************************************************************/
/* 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;
/* we found the downtime we should delete */
if(this_downtime->downtime_id == downtime_id && this_downtime->type == type)
break;
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);
#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);
#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;
}
/* 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;
}
/* 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;
}
/*
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) {
scheduled_downtime *temp_downtime;
scheduled_downtime *next_downtime;
int deleted = 0;
/* Do not allow deletion of everything - must have at least 1 filter on */
if(hostname == NULL && service_description == NULL && start_time == 0 && comment == NULL)
return deleted;
for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = next_downtime) {
next_downtime = temp_downtime->next;
if(start_time != 0 && temp_downtime->start_time != start_time) {
continue;
}
if(comment != NULL && strcmp(temp_downtime->comment, comment) != 0)
continue;
if(temp_downtime->type == HOST_DOWNTIME) {
/* If service is specified, then do not delete the host downtime */
if(service_description != NULL)
continue;
if(hostname != NULL && strcmp(temp_downtime->host_name, hostname) != 0)
continue;
}
else if(temp_downtime->type == SERVICE_DOWNTIME) {
if(hostname != NULL && strcmp(temp_downtime->host_name, hostname) != 0)
continue;
if(service_description != NULL && strcmp(temp_downtime->service_description, service_description) != 0)
continue;
}
unschedule_downtime(temp_downtime->type, temp_downtime->downtime_id);
deleted++;
}
return deleted;
}
#endif
/******************************************************************/
/******************** ADDITION FUNCTIONS **************************/
/******************************************************************/
/* 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;
}
/* 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;
}
/* 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) {
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));
return ERROR;
}
/* allocate memory for the downtime */
if((new_downtime = (scheduled_downtime *)calloc(1, sizeof(scheduled_downtime))) == NULL)
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");
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");
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");
result = ERROR;
}
}
if(comment_data) {
if((new_downtime->comment = (char *)strdup(comment_data)) == NULL)
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;
new_downtime->entry_time = entry_time;
new_downtime->start_time = start_time;
new_downtime->flex_downtime_start = flex_downtime_start;
new_downtime->end_time = end_time;
new_downtime->fixed = (fixed > 0) ? TRUE : FALSE;
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;
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
}
#ifdef NSCORE
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_downtime_data(NEBTYPE_DOWNTIME_LOAD, NEBFLAG_NONE, NEBATTR_NONE, downtime_type, host_name, svc_description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, downtime_id, NULL);
#endif
#endif
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;
log_debug_info(DEBUGL_FUNCTIONS, 0, "sort_downtime()\n");
if(!defer_downtime_sorting)
return OK;
defer_downtime_sorting = 0;
temp_downtime = scheduled_downtime_list;
while(temp_downtime != NULL) {
temp_downtime = temp_downtime->next;
unsorted_downtimes++;
}
if(!unsorted_downtimes)
return OK;
if(!(array = malloc(sizeof(*array) * unsorted_downtimes)))
return ERROR;
while(scheduled_downtime_list) {
array[i++] = scheduled_downtime_list;
scheduled_downtime_list = scheduled_downtime_list->next;
}
qsort((void *)array, i, sizeof(*array), downtime_compar);
scheduled_downtime_list = temp_downtime = array[0];
for(i = 1; i < unsorted_downtimes; i++) {
temp_downtime->next = array[i];
temp_downtime = temp_downtime->next;
}
temp_downtime->next = NULL;
my_free(array);
return OK;
}
/******************************************************************/
/************************ SEARCH FUNCTIONS ************************/
/******************************************************************/
/* finds a specific downtime entry */
scheduled_downtime *find_downtime(int type, unsigned long downtime_id) {
scheduled_downtime *temp_downtime = 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;
}
return NULL;
}
/* finds a specific host downtime entry */
scheduled_downtime *find_host_downtime(unsigned long downtime_id) {
return find_downtime(HOST_DOWNTIME, downtime_id);
}
/* finds a specific service downtime entry */
scheduled_downtime *find_service_downtime(unsigned long downtime_id) {
return find_downtime(SERVICE_DOWNTIME, downtime_id);
}
/******************************************************************/
/********************* CLEANUP FUNCTIONS **************************/
/******************************************************************/
/* frees memory allocated for the scheduled downtime data */
void free_downtime_data(void) {
scheduled_downtime *this_downtime = NULL;
scheduled_downtime *next_downtime = 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;
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);
}
/* reset list pointer */
scheduled_downtime_list = NULL;
return;
}
nagios/common/macros.c 0000664 0000000 0000000 00000313250 12210155146 0015257 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* MACROS.C - Common macro functions for Nagios
*
* Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 08-06-2010
*
* 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/macros.h"
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/statusdata.h"
#include "../include/comments.h"
#ifdef NSCORE
#include "../include/nagios.h"
#else
#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 */
char *macro_user[MAX_USER_MACROS]; /* $USERx$ macros */
struct macro_key_code {
char *name; /* macro key name */
int code; /* numeric macro code, usable in case statements */
int clean_options;
char *value;
};
struct macro_key_code macro_keys[MACRO_X_COUNT];
/*
* These point to their corresponding pointer arrays in global_macros
* AFTER macros have been initialized.
*
* They really only exist so that eventbroker modules that reference
* them won't need to be re-compiled, although modules that rely
* on their values after having run a certain command will require an
* update
*/
char **macro_x = NULL;
/*
* scoped to this file to prevent (unintentional) mischief,
* but see base/notifications.c for how to use it
*/
static nagios_macros global_macros;
nagios_macros *get_global_macros(void) {
return &global_macros;
}
/******************************************************************/
/************************ MACRO FUNCTIONS *************************/
/******************************************************************/
/*
* locate a macro key based on its name by using a binary search
* 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) {
unsigned int high, low = 0;
int value;
struct macro_key_code *key;
high = MACRO_X_COUNT;
while(high - low > 0) {
unsigned int mid = low + ((high - low) / 2);
key = ¯o_keys[mid];
value = strcmp(name, key->name);
if(value == 0) {
return key;
}
if(value > 0)
low = mid + 1;
else
high = mid;
}
return NULL;
}
/*
* replace macros in notification commands with their values,
* the thread-safe version
*/
int process_macros_r(nagios_macros *mac, char *input_buffer, char **output_buffer, int options) {
char *temp_buffer = NULL;
char *save_buffer = NULL;
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;
log_debug_info(DEBUGL_FUNCTIONS, 0, "process_macros_r()\n");
if(output_buffer == NULL)
return ERROR;
*output_buffer = (char *)strdup("");
if(input_buffer == NULL)
return ERROR;
in_macro = FALSE;
log_debug_info(DEBUGL_MACROS, 1, "**** BEGIN MACRO PROCESSING ***********\n");
log_debug_info(DEBUGL_MACROS, 1, "Processing: '%s'\n", input_buffer);
/* use a duplicate of original buffer, so we don't modify the original */
save_buffer = buf_ptr = (input_buffer ? strdup(input_buffer) : NULL);
while(buf_ptr) {
/* save pointer to this working part of buffer */
temp_buffer = buf_ptr;
/* find the next delimiter - terminate preceding string and advance buffer pointer for next run */
if((delim_ptr = strchr(buf_ptr, '$'))) {
delim_ptr[0] = '\x0';
buf_ptr = (char *)delim_ptr + 1;
}
/* no delimiter found - we already have the last of the buffer */
else
buf_ptr = NULL;
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) {
/* add the plain text to the end of the already processed buffer */
*output_buffer = (char *)realloc(*output_buffer, strlen(*output_buffer) + strlen(temp_buffer) + 1);
strcat(*output_buffer, temp_buffer);
log_debug_info(DEBUGL_MACROS, 2, " Not currently in macro. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer);
in_macro = TRUE;
}
/* 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);
/* an error occurred - we couldn't parse the macro, so continue on */
if(result == ERROR) {
log_debug_info(DEBUGL_MACROS, 0, " WARNING: An error occurred processing macro '%s'!\n", temp_buffer);
if(free_macro == TRUE)
my_free(selected_macro);
}
/* we already have a macro... */
if(result == OK)
x = 0;
/* 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);
*output_buffer = (char *)realloc(*output_buffer, strlen(*output_buffer) + 2);
strcat(*output_buffer, "$");
}
/* a non-macro, just some user-defined string between two $s */
else {
log_debug_info(DEBUGL_MACROS, 2, " Non-macro. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer);
/* add the plain text to the end of the already processed buffer */
*output_buffer = (char *)realloc(*output_buffer, strlen(*output_buffer) + strlen(temp_buffer) + 3);
strcat(*output_buffer, "$");
strcat(*output_buffer, temp_buffer);
strcat(*output_buffer, "$");
}
/* 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);
/* URL encode the macro if requested - this allocates new memory */
if(macro_options & URL_ENCODE_MACRO_CHARS) {
original_macro = selected_macro;
selected_macro = get_url_encoded_string(selected_macro);
if(free_macro == TRUE) {
my_free(original_macro);
}
free_macro = TRUE;
}
/* some macros are cleaned... */
if(clean_macro == TRUE || ((macro_options & STRIP_ILLEGAL_MACRO_CHARS) || (macro_options & ESCAPE_MACRO_CHARS))) {
/* 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) {
*output_buffer = (char *)realloc(*output_buffer, strlen(*output_buffer) + strlen(cleaned_macro) + 1);
strcat(*output_buffer, cleaned_macro);
log_debug_info(DEBUGL_MACROS, 2, " Cleaned macro. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer);
}
}
/* others are not cleaned */
else {
/* add the processed macro to the end of the already processed buffer */
if(selected_macro != NULL) {
*output_buffer = (char *)realloc(*output_buffer, strlen(*output_buffer) + strlen(selected_macro) + 1);
strcat(*output_buffer, selected_macro);
log_debug_info(DEBUGL_MACROS, 2, " Uncleaned macro. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer);
}
}
/* free memory if necessary (if we URL encoded the macro or we were told to do so by grab_macro_value()) */
if(free_macro == TRUE)
my_free(selected_macro);
log_debug_info(DEBUGL_MACROS, 2, " Just finished macro. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer);
}
in_macro = FALSE;
}
}
/* free copy of input buffer */
my_free(save_buffer);
log_debug_info(DEBUGL_MACROS, 1, " Done. Final output: '%s'\n", *output_buffer);
log_debug_info(DEBUGL_MACROS, 1, "**** END MACRO PROCESSING *************\n");
return OK;
}
int process_macros(char *input_buffer, char **output_buffer, int options) {
return process_macros_r(&global_macros, input_buffer, output_buffer, options);
}
/******************************************************************/
/********************** MACRO GRAB FUNCTIONS **********************/
/******************************************************************/
/* grab macros that are specific to a particular host */
int grab_host_macros_r(nagios_macros *mac, host *hst) {
/* clear host-related macros */
clear_host_macros_r(mac);
clear_hostgroup_macros_r(mac);
/* save pointer to host */
mac->host_ptr = hst;
mac->hostgroup_ptr = NULL;
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;
}
int grab_host_macros(host *hst) {
return grab_host_macros_r(&global_macros, hst);
}
/* grab hostgroup macros */
int grab_hostgroup_macros_r(nagios_macros *mac, hostgroup *hg) {
/* clear hostgroup macros */
clear_hostgroup_macros_r(mac);
/* save the hostgroup pointer for later */
mac->hostgroup_ptr = hg;
if(hg == NULL)
return ERROR;
return OK;
}
int grab_hostgroup_macros(hostgroup *hg) {
return grab_hostgroup_macros_r(&global_macros, hg);
}
/* grab macros that are specific to a particular service */
int grab_service_macros_r(nagios_macros *mac, service *svc) {
/* clear service-related macros */
clear_service_macros_r(mac);
clear_servicegroup_macros_r(mac);
/* save pointer for later */
mac->service_ptr = svc;
mac->servicegroup_ptr = NULL;
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;
}
int grab_service_macros(service *svc) {
return grab_service_macros_r(&global_macros, svc);
}
/* grab macros that are specific to a particular servicegroup */
int grab_servicegroup_macros_r(nagios_macros *mac, servicegroup *sg) {
/* clear servicegroup macros */
clear_servicegroup_macros_r(mac);
/* save the pointer for later */
mac->servicegroup_ptr = sg;
if(sg == NULL)
return ERROR;
return OK;
}
int grab_servicegroup_macros(servicegroup *sg) {
return grab_servicegroup_macros_r(&global_macros, sg);
}
/* grab macros that are specific to a particular contact */
int grab_contact_macros_r(nagios_macros *mac, contact *cntct) {
/* clear contact-related macros */
clear_contact_macros_r(mac);
clear_contactgroup_macros_r(mac);
/* save pointer to contact for later */
mac->contact_ptr = cntct;
mac->contactgroup_ptr = NULL;
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;
}
int grab_contact_macros(contact *cntct) {
return grab_contact_macros_r(&global_macros, cntct);
}
/******************************************************************/
/******************* MACRO GENERATION FUNCTIONS *******************/
/******************************************************************/
/* this is the big one */
int grab_macro_value_r(nagios_macros *mac, char *macro_buffer, char **output, int *clean_options, int *free_macro) {
char *buf = NULL;
char *ptr = NULL;
char *macro_name = NULL;
char *arg[2] = {NULL, NULL};
contact *temp_contact = NULL;
contactgroup *temp_contactgroup = NULL;
contactsmember *temp_contactsmember = NULL;
char *temp_buffer = NULL;
int delimiter_len = 0;
int x, result = OK;
const struct macro_key_code *mkey;
/* for the early cases, this is the default */
*free_macro = FALSE;
if(output == NULL)
return ERROR;
/* clear the old macro value */
my_free(*output);
if(macro_buffer == NULL || clean_options == NULL || free_macro == NULL)
return ERROR;
/*
* We handle argv and user macros first, since those are by far
* the most commonly accessed ones (3.4 and 1.005 per check,
* respectively). Since neither of them requires that we copy
* the original buffer, we can also get away with some less
* code for these simple cases.
*/
if(strstr(macro_buffer, "ARG") == macro_buffer) {
/* which arg do we want? */
x = atoi(macro_buffer + 3);
if(x <= 0 || x > MAX_COMMAND_ARGUMENTS) {
return ERROR;
}
/* use a pre-computed macro value */
*output = mac->argv[x - 1];
return OK;
}
if(strstr(macro_buffer, "USER") == macro_buffer) {
/* which macro do we want? */
x = atoi(macro_buffer + 4);
if(x <= 0 || x > MAX_USER_MACROS) {
return ERROR;
}
/* use a pre-computed macro value */
*output = macro_user[x - 1];
return OK;
}
/* most frequently used "x" macro gets a shortcut */
if(mac->host_ptr && !strcmp(macro_buffer, "HOSTADDRESS")) {
if(mac->host_ptr->address)
*output = mac->host_ptr->address;
return OK;
}
/* work with a copy of the original buffer */
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;
/* see if there's an argument - if so, this is most likely an on-demand macro */
if((ptr = strchr(buf, ':'))) {
ptr[0] = '\x0';
ptr++;
/* save the first argument - host name, hostgroup name, etc. */
arg[0] = ptr;
/* try and find a second argument */
if((ptr = strchr(ptr, ':'))) {
ptr[0] = '\x0';
ptr++;
/* save second argument - service description or delimiter */
arg[1] = ptr;
}
}
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);
}
/***** CONTACT ADDRESS MACROS *****/
/* NOTE: the code below should be broken out into a separate function */
else if(strstr(macro_name, "CONTACTADDRESS") == macro_name) {
/* which address do we want? */
x = atoi(macro_name + 14) - 1;
/* regular macro */
if(arg[0] == NULL) {
/* use the saved pointer */
if((temp_contact = mac->contact_ptr) == NULL) {
my_free(buf);
return ERROR;
}
/* get the macro value by reference, so no need to free() */
*free_macro = FALSE;
result = grab_contact_address_macro(x, temp_contact, output);
}
/* on-demand macro */
else {
/* on-demand contact macro with a contactgroup and a delimiter */
if(arg[1] != NULL) {
if((temp_contactgroup = find_contactgroup(arg[0])) == NULL)
return ERROR;
delimiter_len = strlen(arg[1]);
/* 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);
if(temp_buffer == NULL)
continue;
/* add macro value to already running macro */
if(*output == NULL)
*output = (char *)strdup(temp_buffer);
else {
if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL)
continue;
strcat(*output, arg[1]);
strcat(*output, temp_buffer);
}
my_free(temp_buffer);
}
}
/* else on-demand contact macro */
else {
/* find the contact */
if((temp_contact = find_contact(arg[0])) == NULL) {
my_free(buf);
return ERROR;
}
/* get the macro value */
result = grab_contact_address_macro(x, temp_contact, output);
}
}
}
/***** CUSTOM VARIABLE MACROS *****/
else if(macro_name[0] == '_') {
/* get the macro value */
result = grab_custom_macro_value_r(mac, macro_name, arg[0], arg[1], output);
}
/* no macro matched... */
else {
log_debug_info(DEBUGL_MACROS, 0, " WARNING: Could not find a macro matching '%s'!\n", macro_name);
result = ERROR;
}
/* free memory */
my_free(buf);
return result;
}
int grab_macro_value(char *macro_buffer, char **output, int *clean_options, int *free_macro) {
return grab_macro_value_r(&global_macros, macro_buffer, output, clean_options, free_macro);
}
int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *arg2, char **output, int *free_macro) {
host *temp_host = NULL;
hostgroup *temp_hostgroup = NULL;
hostsmember *temp_hostsmember = NULL;
service *temp_service = NULL;
servicegroup *temp_servicegroup = NULL;
servicesmember *temp_servicesmember = NULL;
contact *temp_contact = NULL;
contactgroup *temp_contactgroup = NULL;
contactsmember *temp_contactsmember = NULL;
char *temp_buffer = NULL;
int result = OK;
int delimiter_len = 0;
int free_sub_macro = FALSE;
#ifdef NSCORE
register int x;
int authorized = TRUE;
int problem = TRUE;
int hosts_up = 0;
int hosts_down = 0;
int hosts_unreachable = 0;
int hosts_down_unhandled = 0;
int hosts_unreachable_unhandled = 0;
int host_problems = 0;
int host_problems_unhandled = 0;
int services_ok = 0;
int services_warning = 0;
int services_unknown = 0;
int services_critical = 0;
int services_warning_unhandled = 0;
int services_unknown_unhandled = 0;
int services_critical_unhandled = 0;
int service_problems = 0;
int service_problems_unhandled = 0;
#endif
if(output == NULL || free_macro == NULL)
return ERROR;
/* BY DEFAULT, TELL CALLER TO FREE MACRO BUFFER WHEN DONE */
*free_macro = TRUE;
/* handle the macro */
switch(macro_type) {
/***************/
/* HOST MACROS */
/***************/
case MACRO_HOSTNAME:
case MACRO_HOSTALIAS:
case MACRO_HOSTADDRESS:
case MACRO_LASTHOSTCHECK:
case MACRO_LASTHOSTSTATECHANGE:
case MACRO_HOSTOUTPUT:
case MACRO_HOSTPERFDATA:
case MACRO_HOSTSTATE:
case MACRO_HOSTSTATEID:
case MACRO_HOSTATTEMPT:
case MACRO_HOSTEXECUTIONTIME:
case MACRO_HOSTLATENCY:
case MACRO_HOSTDURATION:
case MACRO_HOSTDURATIONSEC:
case MACRO_HOSTDOWNTIME:
case MACRO_HOSTSTATETYPE:
case MACRO_HOSTPERCENTCHANGE:
case MACRO_HOSTACKAUTHOR:
case MACRO_HOSTACKCOMMENT:
case MACRO_LASTHOSTUP:
case MACRO_LASTHOSTDOWN:
case MACRO_LASTHOSTUNREACHABLE:
case MACRO_HOSTCHECKCOMMAND:
case MACRO_HOSTDISPLAYNAME:
case MACRO_HOSTACTIONURL:
case MACRO_HOSTNOTESURL:
case MACRO_HOSTNOTES:
case MACRO_HOSTCHECKTYPE:
case MACRO_LONGHOSTOUTPUT:
case MACRO_HOSTNOTIFICATIONNUMBER:
case MACRO_HOSTNOTIFICATIONID:
case MACRO_HOSTEVENTID:
case MACRO_LASTHOSTEVENTID:
case MACRO_HOSTGROUPNAMES:
case MACRO_HOSTACKAUTHORNAME:
case MACRO_HOSTACKAUTHORALIAS:
case MACRO_MAXHOSTATTEMPTS:
case MACRO_TOTALHOSTSERVICES:
case MACRO_TOTALHOSTSERVICESOK:
case MACRO_TOTALHOSTSERVICESWARNING:
case MACRO_TOTALHOSTSERVICESUNKNOWN:
case MACRO_TOTALHOSTSERVICESCRITICAL:
case MACRO_HOSTPROBLEMID:
case MACRO_LASTHOSTPROBLEMID:
case MACRO_LASTHOSTSTATE:
case MACRO_LASTHOSTSTATEID:
/* a standard host macro */
if(arg2 == NULL) {
/* find the host for on-demand macros */
if(arg1) {
if((temp_host = find_host(arg1)) == NULL)
return ERROR;
}
/* else use saved host pointer */
else if((temp_host = mac->host_ptr) == NULL)
return ERROR;
/* get the host macro value */
result = grab_standard_host_macro_r(mac, macro_type, temp_host, output, free_macro);
}
/* a host macro with a hostgroup name and delimiter */
else {
if((temp_hostgroup = find_hostgroup(arg1)) == NULL)
return ERROR;
delimiter_len = strlen(arg2);
/* 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);
if(temp_buffer == NULL)
continue;
/* add macro value to already running macro */
if(*output == NULL)
*output = (char *)strdup(temp_buffer);
else {
if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL)
continue;
strcat(*output, arg2);
strcat(*output, temp_buffer);
}
if(free_sub_macro == TRUE)
my_free(temp_buffer);
}
}
break;
/********************/
/* HOSTGROUP MACROS */
/********************/
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 */
if(arg1 == NULL) {
if((temp_hostgroup = mac->hostgroup_ptr) == NULL)
return ERROR;
}
/* else find the hostgroup for on-demand macros */
else {
if((temp_hostgroup = find_hostgroup(arg1)) == NULL)
return ERROR;
}
/* get the hostgroup macro value */
result = grab_standard_hostgroup_macro_r(mac, macro_type, temp_hostgroup, output);
break;
/******************/
/* SERVICE MACROS */
/******************/
case MACRO_SERVICEDESC:
case MACRO_SERVICESTATE:
case MACRO_SERVICESTATEID:
case MACRO_SERVICEATTEMPT:
case MACRO_LASTSERVICECHECK:
case MACRO_LASTSERVICESTATECHANGE:
case MACRO_SERVICEOUTPUT:
case MACRO_SERVICEPERFDATA:
case MACRO_SERVICEEXECUTIONTIME:
case MACRO_SERVICELATENCY:
case MACRO_SERVICEDURATION:
case MACRO_SERVICEDURATIONSEC:
case MACRO_SERVICEDOWNTIME:
case MACRO_SERVICESTATETYPE:
case MACRO_SERVICEPERCENTCHANGE:
case MACRO_SERVICEACKAUTHOR:
case MACRO_SERVICEACKCOMMENT:
case MACRO_LASTSERVICEOK:
case MACRO_LASTSERVICEWARNING:
case MACRO_LASTSERVICEUNKNOWN:
case MACRO_LASTSERVICECRITICAL:
case MACRO_SERVICECHECKCOMMAND:
case MACRO_SERVICEDISPLAYNAME:
case MACRO_SERVICEACTIONURL:
case MACRO_SERVICENOTESURL:
case MACRO_SERVICENOTES:
case MACRO_SERVICECHECKTYPE:
case MACRO_LONGSERVICEOUTPUT:
case MACRO_SERVICENOTIFICATIONNUMBER:
case MACRO_SERVICENOTIFICATIONID:
case MACRO_SERVICEEVENTID:
case MACRO_LASTSERVICEEVENTID:
case MACRO_SERVICEGROUPNAMES:
case MACRO_SERVICEACKAUTHORNAME:
case MACRO_SERVICEACKAUTHORALIAS:
case MACRO_MAXSERVICEATTEMPTS:
case MACRO_SERVICEISVOLATILE:
case MACRO_SERVICEPROBLEMID:
case MACRO_LASTSERVICEPROBLEMID:
case MACRO_LASTSERVICESTATE:
case MACRO_LASTSERVICESTATEID:
/* use saved service pointer */
if(arg1 == NULL && arg2 == NULL) {
if((temp_service = mac->service_ptr) == NULL)
return ERROR;
result = grab_standard_service_macro_r(mac, macro_type, temp_service, output, free_macro);
}
/* else and ondemand macro... */
else {
/* if first arg is blank, it means use the current host name */
if(arg1 == NULL || arg1[0] == '\x0') {
if(mac->host_ptr == NULL)
return ERROR;
if((temp_service = find_service(mac->host_ptr->name, arg2))) {
/* get the service macro value */
result = grab_standard_service_macro_r(mac, macro_type, temp_service, output, free_macro);
}
}
/* on-demand macro with both host and service name */
else if((temp_service = find_service(arg1, arg2))) {
/* get the service macro value */
result = grab_standard_service_macro_r(mac, macro_type, temp_service, output, free_macro);
}
/* else we have a service macro with a servicegroup name and a delimiter... */
else if(arg1 && arg2) {
if((temp_servicegroup = find_servicegroup(arg1)) == NULL)
return ERROR;
delimiter_len = strlen(arg2);
/* 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);
if(temp_buffer == NULL)
continue;
/* add macro value to already running macro */
if(*output == NULL)
*output = (char *)strdup(temp_buffer);
else {
if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL)
continue;
strcat(*output, arg2);
strcat(*output, temp_buffer);
}
if(free_sub_macro == TRUE)
my_free(temp_buffer);
}
}
else
return ERROR;
}
break;
/***********************/
/* SERVICEGROUP MACROS */
/***********************/
case MACRO_SERVICEGROUPNAME:
case MACRO_SERVICEGROUPALIAS:
case MACRO_SERVICEGROUPNOTES:
case MACRO_SERVICEGROUPNOTESURL:
case MACRO_SERVICEGROUPACTIONURL:
case MACRO_SERVICEGROUPMEMBERS:
/* a standard servicegroup macro */
/* use the saved servicegroup pointer */
if(arg1 == NULL) {
if((temp_servicegroup = mac->servicegroup_ptr) == NULL)
return ERROR;
}
/* else find the servicegroup for on-demand macros */
else {
if((temp_servicegroup = find_servicegroup(arg1)) == NULL)
return ERROR;
}
/* get the servicegroup macro value */
result = grab_standard_servicegroup_macro_r(mac, macro_type, temp_servicegroup, output);
break;
/******************/
/* CONTACT MACROS */
/******************/
case MACRO_CONTACTNAME:
case MACRO_CONTACTALIAS:
case MACRO_CONTACTEMAIL:
case MACRO_CONTACTPAGER:
case MACRO_CONTACTGROUPNAMES:
/* a standard contact macro */
if(arg2 == NULL) {
/* find the contact for on-demand macros */
if(arg1) {
if((temp_contact = find_contact(arg1)) == NULL)
return ERROR;
}
/* else use saved contact pointer */
else if((temp_contact = mac->contact_ptr) == NULL)
return ERROR;
/* get the contact macro value */
result = grab_standard_contact_macro_r(mac, macro_type, temp_contact, output);
}
/* a contact macro with a contactgroup name and delimiter */
else {
if((temp_contactgroup = find_contactgroup(arg1)) == NULL)
return ERROR;
delimiter_len = strlen(arg2);
/* 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);
if(temp_buffer == NULL)
continue;
/* add macro value to already running macro */
if(*output == NULL)
*output = (char *)strdup(temp_buffer);
else {
if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL)
continue;
strcat(*output, arg2);
strcat(*output, temp_buffer);
}
my_free(temp_buffer);
}
}
break;
/***********************/
/* CONTACTGROUP MACROS */
/***********************/
case MACRO_CONTACTGROUPNAME:
case MACRO_CONTACTGROUPALIAS:
case MACRO_CONTACTGROUPMEMBERS:
/* a standard contactgroup macro */
/* use the saved contactgroup pointer */
if(arg1 == NULL) {
if((temp_contactgroup = mac->contactgroup_ptr) == NULL)
return ERROR;
}
/* else find the contactgroup for on-demand macros */
else {
if((temp_contactgroup = find_contactgroup(arg1)) == NULL)
return ERROR;
}
/* get the contactgroup macro value */
result = grab_standard_contactgroup_macro(macro_type, temp_contactgroup, output);
break;
/***********************/
/* NOTIFICATION MACROS */
/***********************/
case MACRO_NOTIFICATIONTYPE:
case MACRO_NOTIFICATIONNUMBER:
case MACRO_NOTIFICATIONRECIPIENTS:
case MACRO_NOTIFICATIONISESCALATED:
case MACRO_NOTIFICATIONAUTHOR:
case MACRO_NOTIFICATIONAUTHORNAME:
case MACRO_NOTIFICATIONAUTHORALIAS:
case MACRO_NOTIFICATIONCOMMENT:
/* notification macros have already been pre-computed */
*output = mac->x[macro_type];
*free_macro = FALSE;
break;
/********************/
/* DATE/TIME MACROS */
/********************/
case MACRO_LONGDATETIME:
case MACRO_SHORTDATETIME:
case MACRO_DATE:
case MACRO_TIME:
case MACRO_TIMET:
case MACRO_ISVALIDTIME:
case MACRO_NEXTVALIDTIME:
/* calculate macros */
result = grab_datetime_macro_r(mac, macro_type, arg1, arg2, output);
break;
/*****************/
/* STATIC MACROS */
/*****************/
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:
/* no need to do any more work - these are already precomputed for us */
*output = global_macros.x[macro_type];
*free_macro = FALSE;
break;
/******************/
/* SUMMARY MACROS */
/******************/
case MACRO_TOTALHOSTSUP:
case MACRO_TOTALHOSTSDOWN:
case MACRO_TOTALHOSTSUNREACHABLE:
case MACRO_TOTALHOSTSDOWNUNHANDLED:
case MACRO_TOTALHOSTSUNREACHABLEUNHANDLED:
case MACRO_TOTALHOSTPROBLEMS:
case MACRO_TOTALHOSTPROBLEMSUNHANDLED:
case MACRO_TOTALSERVICESOK:
case MACRO_TOTALSERVICESWARNING:
case MACRO_TOTALSERVICESCRITICAL:
case MACRO_TOTALSERVICESUNKNOWN:
case MACRO_TOTALSERVICESWARNINGUNHANDLED:
case MACRO_TOTALSERVICESCRITICALUNHANDLED:
case MACRO_TOTALSERVICESUNKNOWNUNHANDLED:
case MACRO_TOTALSERVICEPROBLEMS:
case MACRO_TOTALSERVICEPROBLEMSUNHANDLED:
#ifdef NSCORE
/* generate summary macros if needed */
if(mac->x[MACRO_TOTALHOSTSUP] == NULL) {
/* get host totals */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
/* filter totals based on contact if necessary */
if(mac->contact_ptr != NULL)
authorized = is_contact_for_host(temp_host, mac->contact_ptr);
if(authorized == TRUE) {
problem = TRUE;
if(temp_host->current_state == HOST_UP && temp_host->has_been_checked == TRUE)
hosts_up++;
else if(temp_host->current_state == HOST_DOWN) {
if(temp_host->scheduled_downtime_depth > 0)
problem = FALSE;
if(temp_host->problem_has_been_acknowledged == TRUE)
problem = FALSE;
if(temp_host->checks_enabled == FALSE)
problem = FALSE;
if(problem == TRUE)
hosts_down_unhandled++;
hosts_down++;
}
else if(temp_host->current_state == HOST_UNREACHABLE) {
if(temp_host->scheduled_downtime_depth > 0)
problem = FALSE;
if(temp_host->problem_has_been_acknowledged == TRUE)
problem = FALSE;
if(temp_host->checks_enabled == FALSE)
problem = FALSE;
if(problem == TRUE)
hosts_down_unhandled++;
hosts_unreachable++;
}
}
}
host_problems = hosts_down + hosts_unreachable;
host_problems_unhandled = hosts_down_unhandled + hosts_unreachable_unhandled;
/* get service totals */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
/* filter totals based on contact if necessary */
if(mac->contact_ptr != NULL)
authorized = is_contact_for_service(temp_service, mac->contact_ptr);
if(authorized == TRUE) {
problem = TRUE;
if(temp_service->current_state == STATE_OK && temp_service->has_been_checked == TRUE)
services_ok++;
else if(temp_service->current_state == STATE_WARNING) {
temp_host = find_host(temp_service->host_name);
if(temp_host != NULL && (temp_host->current_state == HOST_DOWN || temp_host->current_state == HOST_UNREACHABLE))
problem = FALSE;
if(temp_service->scheduled_downtime_depth > 0)
problem = FALSE;
if(temp_service->problem_has_been_acknowledged == TRUE)
problem = FALSE;
if(temp_service->checks_enabled == FALSE)
problem = FALSE;
if(problem == TRUE)
services_warning_unhandled++;
services_warning++;
}
else if(temp_service->current_state == STATE_UNKNOWN) {
temp_host = find_host(temp_service->host_name);
if(temp_host != NULL && (temp_host->current_state == HOST_DOWN || temp_host->current_state == HOST_UNREACHABLE))
problem = FALSE;
if(temp_service->scheduled_downtime_depth > 0)
problem = FALSE;
if(temp_service->problem_has_been_acknowledged == TRUE)
problem = FALSE;
if(temp_service->checks_enabled == FALSE)
problem = FALSE;
if(problem == TRUE)
services_unknown_unhandled++;
services_unknown++;
}
else if(temp_service->current_state == STATE_CRITICAL) {
temp_host = find_host(temp_service->host_name);
if(temp_host != NULL && (temp_host->current_state == HOST_DOWN || temp_host->current_state == HOST_UNREACHABLE))
problem = FALSE;
if(temp_service->scheduled_downtime_depth > 0)
problem = FALSE;
if(temp_service->problem_has_been_acknowledged == TRUE)
problem = FALSE;
if(temp_service->checks_enabled == FALSE)
problem = FALSE;
if(problem == TRUE)
services_critical_unhandled++;
services_critical++;
}
}
}
service_problems = services_warning + services_critical + services_unknown;
service_problems_unhandled = services_warning_unhandled + services_critical_unhandled + services_unknown_unhandled;
/* these macros are time-intensive to compute, and will likely be used together, so save them all for future use */
for(x = MACRO_TOTALHOSTSUP; x <= MACRO_TOTALSERVICEPROBLEMSUNHANDLED; x++)
my_free(mac->x[x]);
asprintf(&mac->x[MACRO_TOTALHOSTSUP], "%d", hosts_up);
asprintf(&mac->x[MACRO_TOTALHOSTSDOWN], "%d", hosts_down);
asprintf(&mac->x[MACRO_TOTALHOSTSUNREACHABLE], "%d", hosts_unreachable);
asprintf(&mac->x[MACRO_TOTALHOSTSDOWNUNHANDLED], "%d", hosts_down_unhandled);
asprintf(&mac->x[MACRO_TOTALHOSTSUNREACHABLEUNHANDLED], "%d", hosts_unreachable_unhandled);
asprintf(&mac->x[MACRO_TOTALHOSTPROBLEMS], "%d", host_problems);
asprintf(&mac->x[MACRO_TOTALHOSTPROBLEMSUNHANDLED], "%d", host_problems_unhandled);
asprintf(&mac->x[MACRO_TOTALSERVICESOK], "%d", services_ok);
asprintf(&mac->x[MACRO_TOTALSERVICESWARNING], "%d", services_warning);
asprintf(&mac->x[MACRO_TOTALSERVICESCRITICAL], "%d", services_critical);
asprintf(&mac->x[MACRO_TOTALSERVICESUNKNOWN], "%d", services_unknown);
asprintf(&mac->x[MACRO_TOTALSERVICESWARNINGUNHANDLED], "%d", services_warning_unhandled);
asprintf(&mac->x[MACRO_TOTALSERVICESCRITICALUNHANDLED], "%d", services_critical_unhandled);
asprintf(&mac->x[MACRO_TOTALSERVICESUNKNOWNUNHANDLED], "%d", services_unknown_unhandled);
asprintf(&mac->x[MACRO_TOTALSERVICEPROBLEMS], "%d", service_problems);
asprintf(&mac->x[MACRO_TOTALSERVICEPROBLEMSUNHANDLED], "%d", service_problems_unhandled);
}
/* return only the macro the user requested */
*output = mac->x[macro_type];
/* tell caller to NOT free memory when done */
*free_macro = FALSE;
#endif
break;
default:
log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED MACRO #%d! THIS IS A BUG!\n", macro_type);
return ERROR;
break;
}
return result;
}
int grab_macrox_value(int macro_type, char *arg1, char *arg2, char **output, int *free_macro) {
return grab_macrox_value_r(&global_macros, macro_type, arg1, arg2, output, free_macro);
}
/* calculates the value of a custom macro */
int grab_custom_macro_value_r(nagios_macros *mac, char *macro_name, char *arg1, char *arg2, char **output) {
host *temp_host = NULL;
hostgroup *temp_hostgroup = NULL;
hostsmember *temp_hostsmember = NULL;
service *temp_service = NULL;
servicegroup *temp_servicegroup = NULL;
servicesmember *temp_servicesmember = NULL;
contact *temp_contact = NULL;
contactgroup *temp_contactgroup = NULL;
contactsmember *temp_contactsmember = NULL;
int delimiter_len = 0;
char *temp_buffer = NULL;
int result = OK;
if(macro_name == NULL || output == NULL)
return ERROR;
/***** CUSTOM HOST MACRO *****/
if(strstr(macro_name, "_HOST") == macro_name) {
/* a standard host macro */
if(arg2 == NULL) {
/* find the host for on-demand macros */
if(arg1) {
if((temp_host = find_host(arg1)) == NULL)
return ERROR;
}
/* else use saved host pointer */
else if((temp_host = mac->host_ptr) == NULL)
return ERROR;
/* get the host macro value */
result = grab_custom_object_macro_r(mac, macro_name + 5, temp_host->custom_variables, output);
}
/* a host macro with a hostgroup name and delimiter */
else {
if((temp_hostgroup = find_hostgroup(arg1)) == NULL)
return ERROR;
delimiter_len = strlen(arg2);
/* 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);
if(temp_buffer == NULL)
continue;
/* add macro value to already running macro */
if(*output == NULL)
*output = (char *)strdup(temp_buffer);
else {
if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL)
continue;
strcat(*output, arg2);
strcat(*output, temp_buffer);
}
my_free(temp_buffer);
}
}
}
/***** CUSTOM SERVICE MACRO *****/
else if(strstr(macro_name, "_SERVICE") == macro_name) {
/* use saved service pointer */
if(arg1 == NULL && arg2 == NULL) {
if((temp_service = mac->service_ptr) == NULL)
return ERROR;
/* get the service macro value */
result = grab_custom_object_macro_r(mac, macro_name + 8, temp_service->custom_variables, output);
}
/* else and ondemand macro... */
else {
/* if first arg is blank, it means use the current host name */
if(mac->host_ptr == NULL)
return ERROR;
if((temp_service = find_service((mac->host_ptr) ? mac->host_ptr->name : NULL, arg2))) {
/* get the service macro value */
result = grab_custom_object_macro_r(mac, macro_name + 8, temp_service->custom_variables, output);
}
/* else we have a service macro with a servicegroup name and a delimiter... */
else {
if((temp_servicegroup = find_servicegroup(arg1)) == NULL)
return ERROR;
delimiter_len = strlen(arg2);
/* 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);
if(temp_buffer == NULL)
continue;
/* add macro value to already running macro */
if(*output == NULL)
*output = (char *)strdup(temp_buffer);
else {
if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL)
continue;
strcat(*output, arg2);
strcat(*output, temp_buffer);
}
my_free(temp_buffer);
}
}
}
}
/***** CUSTOM CONTACT VARIABLE *****/
else if(strstr(macro_name, "_CONTACT") == macro_name) {
/* a standard contact macro */
if(arg2 == NULL) {
/* find the contact for on-demand macros */
if(arg1) {
if((temp_contact = find_contact(arg1)) == NULL)
return ERROR;
}
/* else use saved contact pointer */
else if((temp_contact = mac->contact_ptr) == NULL)
return ERROR;
/* get the contact macro value */
result = grab_custom_object_macro_r(mac, macro_name + 8, temp_contact->custom_variables, output);
}
/* a contact macro with a contactgroup name and delimiter */
else {
if((temp_contactgroup = find_contactgroup(arg1)) == NULL)
return ERROR;
delimiter_len = strlen(arg2);
/* 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);
if(temp_buffer == NULL)
continue;
/* add macro value to already running macro */
if(*output == NULL)
*output = (char *)strdup(temp_buffer);
else {
if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_buffer) + delimiter_len + 1)) == NULL)
continue;
strcat(*output, arg2);
strcat(*output, temp_buffer);
}
my_free(temp_buffer);
}
}
}
else
return ERROR;
return result;
}
int grab_custom_macro_value(char *macro_name, char *arg1, char *arg2, char **output) {
return grab_custom_macro_value_r(&global_macros, macro_name, arg1, arg2, output);
}
/* calculates a date/time macro */
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 next_valid_time = 0L;
#endif
if(output == NULL)
return ERROR;
/* get the current time */
time(¤t_time);
/* parse args, do prep work */
switch(macro_type) {
case MACRO_ISVALIDTIME:
case MACRO_NEXTVALIDTIME:
/* find the timeperiod */
if((temp_timeperiod = find_timeperiod(arg1)) == NULL)
return ERROR;
/* what timestamp should we use? */
if(arg2)
test_time = (time_t)strtoul(arg2, NULL, 0);
else
test_time = current_time;
break;
default:
break;
}
/* calculate the value */
switch(macro_type) {
case MACRO_LONGDATETIME:
if(*output == NULL)
*output = (char *)malloc(MAX_DATETIME_LENGTH);
if(*output)
get_datetime_string(¤t_time, *output, MAX_DATETIME_LENGTH, LONG_DATE_TIME);
break;
case MACRO_SHORTDATETIME:
if(*output == NULL)
*output = (char *)malloc(MAX_DATETIME_LENGTH);
if(*output)
get_datetime_string(¤t_time, *output, MAX_DATETIME_LENGTH, SHORT_DATE_TIME);
break;
case MACRO_DATE:
if(*output == NULL)
*output = (char *)malloc(MAX_DATETIME_LENGTH);
if(*output)
get_datetime_string(¤t_time, *output, MAX_DATETIME_LENGTH, SHORT_DATE);
break;
case MACRO_TIME:
if(*output == NULL)
*output = (char *)malloc(MAX_DATETIME_LENGTH);
if(*output)
get_datetime_string(¤t_time, *output, MAX_DATETIME_LENGTH, SHORT_TIME);
break;
case MACRO_TIMET:
asprintf(output, "%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);
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);
break;
#endif
default:
return ERROR;
break;
}
return OK;
}
int grab_datetime_macro(int macro_type, char *arg1, char *arg2, char **output) {
return grab_datetime_macro_r(&global_macros, macro_type, arg1, arg2, output);
}
/* calculates a host macro */
int grab_standard_host_macro_r(nagios_macros *mac, int macro_type, host *temp_host, char **output, int *free_macro) {
char *temp_buffer = NULL;
#ifdef NSCORE
hostgroup *temp_hostgroup = NULL;
servicesmember *temp_servicesmember = NULL;
service *temp_service = NULL;
objectlist *temp_objectlist = NULL;
time_t current_time = 0L;
unsigned long duration = 0L;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
char *buf1 = NULL;
char *buf2 = NULL;
int total_host_services = 0;
int total_host_services_ok = 0;
int total_host_services_warning = 0;
int total_host_services_unknown = 0;
int total_host_services_critical = 0;
#endif
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);
break;
case MACRO_HOSTDISPLAYNAME:
if(temp_host->display_name)
*output = (char *)strdup(temp_host->display_name);
break;
case MACRO_HOSTALIAS:
*output = (char *)strdup(temp_host->alias);
break;
case MACRO_HOSTADDRESS:
*output = (char *)strdup(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");
break;
case MACRO_HOSTSTATEID:
asprintf(output, "%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");
break;
case MACRO_LASTHOSTSTATEID:
asprintf(output, "%d", temp_host->last_state);
break;
case MACRO_HOSTCHECKTYPE:
asprintf(output, "%s", (temp_host->check_type == HOST_CHECK_PASSIVE) ? "PASSIVE" : "ACTIVE");
break;
case MACRO_HOSTSTATETYPE:
asprintf(output, "%s", (temp_host->state_type == HARD_STATE) ? "HARD" : "SOFT");
break;
case MACRO_HOSTOUTPUT:
if(temp_host->plugin_output)
*output = (char *)strdup(temp_host->plugin_output);
break;
case MACRO_LONGHOSTOUTPUT:
if(temp_host->long_plugin_output)
*output = (char *)strdup(temp_host->long_plugin_output);
break;
case MACRO_HOSTPERFDATA:
if(temp_host->perf_data)
*output = (char *)strdup(temp_host->perf_data);
break;
#endif
case MACRO_HOSTCHECKCOMMAND:
if(temp_host->host_check_command)
*output = (char *)strdup(temp_host->host_check_command);
break;
#ifdef NSCORE
case MACRO_HOSTATTEMPT:
asprintf(output, "%d", temp_host->current_attempt);
break;
case MACRO_MAXHOSTATTEMPTS:
asprintf(output, "%d", temp_host->max_attempts);
break;
case MACRO_HOSTDOWNTIME:
asprintf(output, "%d", temp_host->scheduled_downtime_depth);
break;
case MACRO_HOSTPERCENTCHANGE:
asprintf(output, "%.2f", temp_host->percent_state_change);
break;
case MACRO_HOSTDURATIONSEC:
case MACRO_HOSTDURATION:
time(¤t_time);
duration = (unsigned long)(current_time - temp_host->last_state_change);
if(macro_type == MACRO_HOSTDURATIONSEC)
asprintf(output, "%lu", duration);
else {
days = duration / 86400;
duration -= (days * 86400);
hours = duration / 3600;
duration -= (hours * 3600);
minutes = duration / 60;
duration -= (minutes * 60);
seconds = duration;
asprintf(output, "%dd %dh %dm %ds", days, hours, minutes, seconds);
}
break;
case MACRO_HOSTEXECUTIONTIME:
asprintf(output, "%.3f", temp_host->execution_time);
break;
case MACRO_HOSTLATENCY:
asprintf(output, "%.3f", temp_host->latency);
break;
case MACRO_LASTHOSTCHECK:
asprintf(output, "%lu", (unsigned long)temp_host->last_check);
break;
case MACRO_LASTHOSTSTATECHANGE:
asprintf(output, "%lu", (unsigned long)temp_host->last_state_change);
break;
case MACRO_LASTHOSTUP:
asprintf(output, "%lu", (unsigned long)temp_host->last_time_up);
break;
case MACRO_LASTHOSTDOWN:
asprintf(output, "%lu", (unsigned long)temp_host->last_time_down);
break;
case MACRO_LASTHOSTUNREACHABLE:
asprintf(output, "%lu", (unsigned long)temp_host->last_time_unreachable);
break;
case MACRO_HOSTNOTIFICATIONNUMBER:
asprintf(output, "%d", temp_host->current_notification_number);
break;
case MACRO_HOSTNOTIFICATIONID:
asprintf(output, "%lu", temp_host->current_notification_id);
break;
case MACRO_HOSTEVENTID:
asprintf(output, "%lu", temp_host->current_event_id);
break;
case MACRO_LASTHOSTEVENTID:
asprintf(output, "%lu", temp_host->last_event_id);
break;
case MACRO_HOSTPROBLEMID:
asprintf(output, "%lu", temp_host->current_problem_id);
break;
case MACRO_LASTHOSTPROBLEMID:
asprintf(output, "%lu", temp_host->last_problem_id);
break;
#endif
case MACRO_HOSTACTIONURL:
if(temp_host->action_url)
*output = (char *)strdup(temp_host->action_url);
break;
case MACRO_HOSTNOTESURL:
if(temp_host->notes_url)
*output = (char *)strdup(temp_host->notes_url);
break;
case MACRO_HOSTNOTES:
if(temp_host->notes)
*output = (char *)strdup(temp_host->notes);
break;
#ifdef NSCORE
case MACRO_HOSTGROUPNAMES:
/* find all hostgroups this host is associated with */
for(temp_objectlist = temp_host->hostgroups_ptr; temp_objectlist != NULL; temp_objectlist = temp_objectlist->next) {
if((temp_hostgroup = (hostgroup *)temp_objectlist->object_ptr) == NULL)
continue;
asprintf(&buf1, "%s%s%s", (buf2) ? buf2 : "", (buf2) ? "," : "", temp_hostgroup->group_name);
my_free(buf2);
buf2 = buf1;
}
if(buf2) {
*output = (char *)strdup(buf2);
my_free(buf2);
}
break;
case MACRO_TOTALHOSTSERVICES:
case MACRO_TOTALHOSTSERVICESOK:
case MACRO_TOTALHOSTSERVICESWARNING:
case MACRO_TOTALHOSTSERVICESUNKNOWN:
case MACRO_TOTALHOSTSERVICESCRITICAL:
/* generate host service summary macros (if they haven't already been computed) */
if(mac->x[MACRO_TOTALHOSTSERVICES] == NULL) {
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
total_host_services++;
switch(temp_service->current_state) {
case STATE_OK:
total_host_services_ok++;
break;
case STATE_WARNING:
total_host_services_warning++;
break;
case STATE_UNKNOWN:
total_host_services_unknown++;
break;
case STATE_CRITICAL:
total_host_services_critical++;
break;
default:
break;
}
}
/* 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);
}
/* return only the macro the user requested */
*output = mac->x[macro_type];
/* tell caller to NOT free memory when done */
*free_macro = FALSE;
break;
#endif
/***************/
/* MISC MACROS */
/***************/
case MACRO_HOSTACKAUTHOR:
case MACRO_HOSTACKAUTHORNAME:
case MACRO_HOSTACKAUTHORALIAS:
case MACRO_HOSTACKCOMMENT:
/* 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:
log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED HOST MACRO #%d! THIS IS A BUG!\n", macro_type);
return ERROR;
break;
}
/* post-processing */
/* notes, notes URL and action URL macros may themselves contain macros, so process them... */
switch(macro_type) {
case MACRO_HOSTACTIONURL:
case MACRO_HOSTNOTESURL:
process_macros_r(mac, *output, &temp_buffer, URL_ENCODE_MACRO_CHARS);
my_free(*output);
*output = temp_buffer;
break;
case MACRO_HOSTNOTES:
process_macros_r(mac, *output, &temp_buffer, 0);
my_free(*output);
*output = temp_buffer;
break;
default:
break;
}
return OK;
}
int grab_standard_host_macro(int macro_type, host *temp_host, char **output, int *free_macro) {
return grab_standard_host_macro_r(&global_macros, macro_type, temp_host, output, free_macro);
}
/* computes a hostgroup macro */
int grab_standard_hostgroup_macro_r(nagios_macros *mac, int macro_type, hostgroup *temp_hostgroup, char **output) {
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;
/* get the macro value */
switch(macro_type) {
case MACRO_HOSTGROUPNAME:
*output = (char *)strdup(temp_hostgroup->group_name);
break;
case MACRO_HOSTGROUPALIAS:
if(temp_hostgroup->alias)
*output = (char *)strdup(temp_hostgroup->alias);
break;
case MACRO_HOSTGROUPMEMBERS:
/* 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;
}
else {
temp_len += strlen(temp_hostsmember->host_name) + 2;
}
}
/* allocate or reallocate the memory buffer */
if(*output == NULL) {
*output = (char *)malloc(temp_len);
}
else {
init_len = strlen(*output);
temp_len += init_len;
*output = (char *)realloc(*output, temp_len);
}
/* now fill in the string with the member names */
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);
}
else {
init_len += sprintf(temp_buffer, ",%s", temp_hostsmember->host_name);
}
}
break;
case MACRO_HOSTGROUPACTIONURL:
if(temp_hostgroup->action_url)
*output = (char *)strdup(temp_hostgroup->action_url);
break;
case MACRO_HOSTGROUPNOTESURL:
if(temp_hostgroup->notes_url)
*output = (char *)strdup(temp_hostgroup->notes_url);
break;
case MACRO_HOSTGROUPNOTES:
if(temp_hostgroup->notes)
*output = (char *)strdup(temp_hostgroup->notes);
break;
default:
log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED HOSTGROUP MACRO #%d! THIS IS A BUG!\n", macro_type);
return ERROR;
break;
}
/* post-processing */
/* notes, notes URL and action URL macros may themselves contain macros, so process them... */
switch(macro_type) {
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:
break;
}
return OK;
}
int grab_standard_hostgroup_macro(int macro_type, hostgroup *temp_hostgroup, char **output) {
return grab_standard_hostgroup_macro_r(&global_macros, macro_type, temp_hostgroup, output);
}
/* computes a service macro */
int grab_standard_service_macro_r(nagios_macros *mac, int macro_type, service *temp_service, char **output, int *free_macro) {
char *temp_buffer = NULL;
#ifdef NSCORE
servicegroup *temp_servicegroup = NULL;
objectlist *temp_objectlist = NULL;
time_t current_time = 0L;
unsigned long duration = 0L;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
char *buf1 = NULL;
char *buf2 = NULL;
#endif
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);
break;
case MACRO_SERVICEDISPLAYNAME:
if(temp_service->display_name)
*output = (char *)strdup(temp_service->display_name);
break;
#ifdef NSCORE
case MACRO_SERVICEOUTPUT:
if(temp_service->plugin_output)
*output = (char *)strdup(temp_service->plugin_output);
break;
case MACRO_LONGSERVICEOUTPUT:
if(temp_service->long_plugin_output)
*output = (char *)strdup(temp_service->long_plugin_output);
break;
case MACRO_SERVICEPERFDATA:
if(temp_service->perf_data)
*output = (char *)strdup(temp_service->perf_data);
break;
#endif
case MACRO_SERVICECHECKCOMMAND:
if(temp_service->service_check_command)
*output = (char *)strdup(temp_service->service_check_command);
break;
#ifdef NSCORE
case MACRO_SERVICECHECKTYPE:
*output = (char *)strdup((temp_service->check_type == SERVICE_CHECK_PASSIVE) ? "PASSIVE" : "ACTIVE");
break;
case MACRO_SERVICESTATETYPE:
*output = (char *)strdup((temp_service->state_type == HARD_STATE) ? "HARD" : "SOFT");
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");
break;
case MACRO_SERVICESTATEID:
asprintf(output, "%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");
break;
case MACRO_LASTSERVICESTATEID:
asprintf(output, "%d", temp_service->last_state);
break;
#endif
case MACRO_SERVICEISVOLATILE:
asprintf(output, "%d", temp_service->is_volatile);
break;
#ifdef NSCORE
case MACRO_SERVICEATTEMPT:
asprintf(output, "%d", temp_service->current_attempt);
break;
case MACRO_MAXSERVICEATTEMPTS:
asprintf(output, "%d", temp_service->max_attempts);
break;
case MACRO_SERVICEEXECUTIONTIME:
asprintf(output, "%.3f", temp_service->execution_time);
break;
case MACRO_SERVICELATENCY:
asprintf(output, "%.3f", temp_service->latency);
break;
case MACRO_LASTSERVICECHECK:
asprintf(output, "%lu", (unsigned long)temp_service->last_check);
break;
case MACRO_LASTSERVICESTATECHANGE:
asprintf(output, "%lu", (unsigned long)temp_service->last_state_change);
break;
case MACRO_LASTSERVICEOK:
asprintf(output, "%lu", (unsigned long)temp_service->last_time_ok);
break;
case MACRO_LASTSERVICEWARNING:
asprintf(output, "%lu", (unsigned long)temp_service->last_time_warning);
break;
case MACRO_LASTSERVICEUNKNOWN:
asprintf(output, "%lu", (unsigned long)temp_service->last_time_unknown);
break;
case MACRO_LASTSERVICECRITICAL:
asprintf(output, "%lu", (unsigned long)temp_service->last_time_critical);
break;
case MACRO_SERVICEDOWNTIME:
asprintf(output, "%d", temp_service->scheduled_downtime_depth);
break;
case MACRO_SERVICEPERCENTCHANGE:
asprintf(output, "%.2f", temp_service->percent_state_change);
break;
case MACRO_SERVICEDURATIONSEC:
case MACRO_SERVICEDURATION:
time(¤t_time);
duration = (unsigned long)(current_time - temp_service->last_state_change);
/* get the state duration in seconds */
if(macro_type == MACRO_SERVICEDURATIONSEC)
asprintf(output, "%lu", duration);
/* get the state duration */
else {
days = duration / 86400;
duration -= (days * 86400);
hours = duration / 3600;
duration -= (hours * 3600);
minutes = duration / 60;
duration -= (minutes * 60);
seconds = duration;
asprintf(output, "%dd %dh %dm %ds", days, hours, minutes, seconds);
}
break;
case MACRO_SERVICENOTIFICATIONNUMBER:
asprintf(output, "%d", temp_service->current_notification_number);
break;
case MACRO_SERVICENOTIFICATIONID:
asprintf(output, "%lu", temp_service->current_notification_id);
break;
case MACRO_SERVICEEVENTID:
asprintf(output, "%lu", temp_service->current_event_id);
break;
case MACRO_LASTSERVICEEVENTID:
asprintf(output, "%lu", temp_service->last_event_id);
break;
case MACRO_SERVICEPROBLEMID:
asprintf(output, "%lu", temp_service->current_problem_id);
break;
case MACRO_LASTSERVICEPROBLEMID:
asprintf(output, "%lu", temp_service->last_problem_id);
break;
#endif
case MACRO_SERVICEACTIONURL:
if(temp_service->action_url)
*output = (char *)strdup(temp_service->action_url);
break;
case MACRO_SERVICENOTESURL:
if(temp_service->notes_url)
*output = (char *)strdup(temp_service->notes_url);
break;
case MACRO_SERVICENOTES:
if(temp_service->notes)
*output = (char *)strdup(temp_service->notes);
break;
#ifdef NSCORE
case MACRO_SERVICEGROUPNAMES:
/* find all servicegroups this service is associated with */
for(temp_objectlist = temp_service->servicegroups_ptr; temp_objectlist != NULL; temp_objectlist = temp_objectlist->next) {
if((temp_servicegroup = (servicegroup *)temp_objectlist->object_ptr) == NULL)
continue;
asprintf(&buf1, "%s%s%s", (buf2) ? buf2 : "", (buf2) ? "," : "", temp_servicegroup->group_name);
my_free(buf2);
buf2 = buf1;
}
if(buf2) {
*output = (char *)strdup(buf2);
my_free(buf2);
}
break;
#endif
/***************/
/* MISC MACROS */
/***************/
case MACRO_SERVICEACKAUTHOR:
case MACRO_SERVICEACKAUTHORNAME:
case MACRO_SERVICEACKAUTHORALIAS:
case MACRO_SERVICEACKCOMMENT:
/* 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:
log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED SERVICE MACRO #%d! THIS IS A BUG!\n", macro_type);
return ERROR;
break;
}
/* post-processing */
/* notes, notes URL and action URL macros may themselves contain macros, so process them... */
switch(macro_type) {
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:
break;
}
return OK;
}
int grab_standard_service_macro(int macro_type, service *temp_service, char **output, int *free_macro) {
return grab_standard_service_macro_r(&global_macros, macro_type, temp_service, output, free_macro);
}
/* computes a servicegroup macro */
int grab_standard_servicegroup_macro_r(nagios_macros *mac, int macro_type, servicegroup *temp_servicegroup, char **output) {
servicesmember *temp_servicesmember = NULL;
char *temp_buffer = NULL;
unsigned int temp_len = 0;
unsigned int init_len = 0;
if(temp_servicegroup == NULL || output == NULL)
return ERROR;
/* get the macro value */
switch(macro_type) {
case MACRO_SERVICEGROUPNAME:
*output = (char *)strdup(temp_servicegroup->group_name);
break;
case MACRO_SERVICEGROUPALIAS:
if(temp_servicegroup->alias)
*output = (char *)strdup(temp_servicegroup->alias);
break;
case MACRO_SERVICEGROUPMEMBERS:
/* make the calculations for total string length */
for(temp_servicesmember = temp_servicegroup->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if(temp_servicesmember->host_name == NULL || temp_servicesmember->service_description == NULL)
continue;
if(temp_len == 0) {
temp_len += strlen(temp_servicesmember->host_name) + strlen(temp_servicesmember->service_description) + 2;
}
else {
temp_len += strlen(temp_servicesmember->host_name) + strlen(temp_servicesmember->service_description) + 3;
}
}
/* allocate or reallocate the memory buffer */
if(*output == NULL) {
*output = (char *)malloc(temp_len);
}
else {
init_len = strlen(*output);
temp_len += init_len;
*output = (char *)realloc(*output, temp_len);
}
/* now fill in the string with the group members */
for(temp_servicesmember = temp_servicegroup->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if(temp_servicesmember->host_name == NULL || temp_servicesmember->service_description == 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,%s", temp_servicesmember->host_name, temp_servicesmember->service_description);
}
else { /* Now we need to write ",%s,%s" */
init_len += sprintf(temp_buffer, ",%s,%s", temp_servicesmember->host_name, temp_servicesmember->service_description);
}
}
break;
case MACRO_SERVICEGROUPACTIONURL:
if(temp_servicegroup->action_url)
*output = (char *)strdup(temp_servicegroup->action_url);
break;
case MACRO_SERVICEGROUPNOTESURL:
if(temp_servicegroup->notes_url)
*output = (char *)strdup(temp_servicegroup->notes_url);
break;
case MACRO_SERVICEGROUPNOTES:
if(temp_servicegroup->notes)
*output = (char *)strdup(temp_servicegroup->notes);
break;
default:
log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED SERVICEGROUP MACRO #%d! THIS IS A BUG!\n", macro_type);
return ERROR;
}
/* post-processing */
/* notes, notes URL and action URL macros may themselves contain macros, so process them... */
switch(macro_type) {
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:
break;
}
return OK;
}
int grab_standard_servicegroup_macro(int macro_type, servicegroup *temp_servicegroup, char **output) {
return grab_standard_servicegroup_macro_r(&global_macros, macro_type, temp_servicegroup, output);
}
/* computes a contact macro */
int grab_standard_contact_macro_r(nagios_macros *mac, int macro_type, contact *temp_contact, char **output) {
#ifdef NSCORE
contactgroup *temp_contactgroup = NULL;
objectlist *temp_objectlist = NULL;
char *buf1 = NULL;
char *buf2 = NULL;
#endif
if(temp_contact == NULL || output == NULL)
return ERROR;
/* get the macro value */
switch(macro_type) {
case MACRO_CONTACTNAME:
*output = (char *)strdup(temp_contact->name);
break;
case MACRO_CONTACTALIAS:
*output = (char *)strdup(temp_contact->alias);
break;
case MACRO_CONTACTEMAIL:
if(temp_contact->email)
*output = (char *)strdup(temp_contact->email);
break;
case MACRO_CONTACTPAGER:
if(temp_contact->pager)
*output = (char *)strdup(temp_contact->pager);
break;
#ifdef NSCORE
case MACRO_CONTACTGROUPNAMES:
/* get the contactgroup names */
/* find all contactgroups this contact is a member of */
for(temp_objectlist = temp_contact->contactgroups_ptr; temp_objectlist != NULL; temp_objectlist = temp_objectlist->next) {
if((temp_contactgroup = (contactgroup *)temp_objectlist->object_ptr) == NULL)
continue;
asprintf(&buf1, "%s%s%s", (buf2) ? buf2 : "", (buf2) ? "," : "", temp_contactgroup->group_name);
my_free(buf2);
buf2 = buf1;
}
if(buf2) {
*output = (char *)strdup(buf2);
my_free(buf2);
}
break;
#endif
default:
log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED CONTACT MACRO #%d! THIS IS A BUG!\n", macro_type);
return ERROR;
}
return OK;
}
int grab_standard_contact_macro(int macro_type, contact *temp_contact, char **output) {
return grab_standard_contact_macro_r(&global_macros, macro_type, temp_contact, output);
}
/* computes a contact address macro */
int grab_contact_address_macro(int macro_num, contact *temp_contact, char **output) {
if(macro_num < 0 || macro_num >= MAX_CONTACT_ADDRESSES)
return ERROR;
if(temp_contact == NULL || output == NULL)
return ERROR;
/* get the macro */
if(temp_contact->address[macro_num])
*output = temp_contact->address[macro_num];
return OK;
}
/* computes a contactgroup macro */
int grab_standard_contactgroup_macro(int macro_type, contactgroup *temp_contactgroup, char **output) {
contactsmember *temp_contactsmember = NULL;
if(temp_contactgroup == NULL || output == NULL)
return ERROR;
/* get the macro value */
switch(macro_type) {
case MACRO_CONTACTGROUPNAME:
*output = (char *)strdup(temp_contactgroup->group_name);
break;
case MACRO_CONTACTGROUPALIAS:
if(temp_contactgroup->alias)
*output = (char *)strdup(temp_contactgroup->alias);
break;
case MACRO_CONTACTGROUPMEMBERS:
/* get the member list */
for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
if(temp_contactsmember->contact_name == NULL)
continue;
if(*output == NULL)
*output = (char *)strdup(temp_contactsmember->contact_name);
else if((*output = (char *)realloc(*output, strlen(*output) + strlen(temp_contactsmember->contact_name) + 2))) {
strcat(*output, ",");
strcat(*output, temp_contactsmember->contact_name);
}
}
break;
default:
log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED CONTACTGROUP MACRO #%d! THIS IS A BUG!\n", macro_type);
return ERROR;
}
return OK;
}
/* computes a custom object macro */
int grab_custom_object_macro_r(nagios_macros *mac, char *macro_name, customvariablesmember *vars, char **output) {
customvariablesmember *temp_customvariablesmember = NULL;
int result = ERROR;
if(macro_name == NULL || vars == NULL || output == NULL)
return ERROR;
/* get the custom variable */
for(temp_customvariablesmember = vars; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
if(temp_customvariablesmember->variable_name == NULL)
continue;
if(!strcmp(macro_name, temp_customvariablesmember->variable_name)) {
if(temp_customvariablesmember->variable_value)
*output = (char *)strdup(temp_customvariablesmember->variable_value);
result = OK;
break;
}
}
return result;
}
int grab_custom_object_macro(char *macro_name, customvariablesmember *vars, char **output) {
return grab_custom_object_macro_r(&global_macros, macro_name, vars, output);
}
/******************************************************************/
/********************* MACRO STRING FUNCTIONS *********************/
/******************************************************************/
/* cleans illegal characters in macros before output */
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;
if(macro == NULL)
return "";
len = (int)strlen(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];
}
macro[y++] = '\x0';
}
#ifdef ON_HOLD_FOR_NOW
/* escape nasty character in macro */
if(options & ESCAPE_MACRO_CHARS) {
}
#endif
return macro;
}
/* encodes a string in proper URL format */
char *get_url_encoded_string(char *input) {
register int x = 0;
register int y = 0;
char *encoded_url_string = NULL;
char temp_expansion[6] = "";
/* bail if no input */
if(input == NULL)
return NULL;
/* allocate enough memory to escape all characters if necessary */
if((encoded_url_string = (char *)malloc((strlen(input) * 3) + 1)) == NULL)
return NULL;
/* check/encode all characters */
for(x = 0, y = 0; input[x] != (char)'\x0'; 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++;
}
/* 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);
y += 3;
}
}
/* terminate encoded string */
encoded_url_string[y] = '\x0';
return encoded_url_string;
}
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);
}
/******************************************************************/
/***************** MACRO INITIALIZATION FUNCTIONS *****************/
/******************************************************************/
/* initializes global macros */
int init_macros(void) {
init_macrox_names();
int x;
/*
* non-volatile macros are free()'d when they're set.
* We must do this in order to not lose the constant
* ones when we get SIGHUP or a RESTART_PROGRAM event
* from the command fifo. Otherwise a memset() would
* have been better.
*/
clear_volatile_macros_r(&global_macros);
/* backwards compatibility hack */
macro_x = global_macros.x;
/*
* Now build an ordered list of X macro names so we can
* do binary lookups later and avoid a ton of strcmp()'s
* for each and every check that gets run. A hash table
* is actually slower, since the most frequently used
* 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++) {
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;
}
}
qsort(macro_keys, x, sizeof(struct macro_key_code), macro_key_cmp);
return OK;
}
/*
* initializes the names of macros, using this nifty little macro
* which ensures we never add any typos to the list
*/
#define add_macrox_name(name) macro_x_names[MACRO_##name] = strdup(#name)
int init_macrox_names(void) {
register int x = 0;
/* initialize macro names */
for(x = 0; x < MACRO_X_COUNT; x++)
macro_x_names[x] = NULL;
/* initialize each macro name */
add_macrox_name(HOSTNAME);
add_macrox_name(HOSTALIAS);
add_macrox_name(HOSTADDRESS);
add_macrox_name(SERVICEDESC);
add_macrox_name(SERVICESTATE);
add_macrox_name(SERVICESTATEID);
add_macrox_name(SERVICEATTEMPT);
add_macrox_name(SERVICEISVOLATILE);
add_macrox_name(LONGDATETIME);
add_macrox_name(SHORTDATETIME);
add_macrox_name(DATE);
add_macrox_name(TIME);
add_macrox_name(TIMET);
add_macrox_name(LASTHOSTCHECK);
add_macrox_name(LASTSERVICECHECK);
add_macrox_name(LASTHOSTSTATECHANGE);
add_macrox_name(LASTSERVICESTATECHANGE);
add_macrox_name(HOSTOUTPUT);
add_macrox_name(SERVICEOUTPUT);
add_macrox_name(HOSTPERFDATA);
add_macrox_name(SERVICEPERFDATA);
add_macrox_name(CONTACTNAME);
add_macrox_name(CONTACTALIAS);
add_macrox_name(CONTACTEMAIL);
add_macrox_name(CONTACTPAGER);
add_macrox_name(ADMINEMAIL);
add_macrox_name(ADMINPAGER);
add_macrox_name(HOSTSTATE);
add_macrox_name(HOSTSTATEID);
add_macrox_name(HOSTATTEMPT);
add_macrox_name(NOTIFICATIONTYPE);
add_macrox_name(NOTIFICATIONNUMBER);
add_macrox_name(NOTIFICATIONISESCALATED);
add_macrox_name(HOSTEXECUTIONTIME);
add_macrox_name(SERVICEEXECUTIONTIME);
add_macrox_name(HOSTLATENCY);
add_macrox_name(SERVICELATENCY);
add_macrox_name(HOSTDURATION);
add_macrox_name(SERVICEDURATION);
add_macrox_name(HOSTDURATIONSEC);
add_macrox_name(SERVICEDURATIONSEC);
add_macrox_name(HOSTDOWNTIME);
add_macrox_name(SERVICEDOWNTIME);
add_macrox_name(HOSTSTATETYPE);
add_macrox_name(SERVICESTATETYPE);
add_macrox_name(HOSTPERCENTCHANGE);
add_macrox_name(SERVICEPERCENTCHANGE);
add_macrox_name(HOSTGROUPNAME);
add_macrox_name(HOSTGROUPALIAS);
add_macrox_name(SERVICEGROUPNAME);
add_macrox_name(SERVICEGROUPALIAS);
add_macrox_name(HOSTACKAUTHOR);
add_macrox_name(HOSTACKCOMMENT);
add_macrox_name(SERVICEACKAUTHOR);
add_macrox_name(SERVICEACKCOMMENT);
add_macrox_name(LASTSERVICEOK);
add_macrox_name(LASTSERVICEWARNING);
add_macrox_name(LASTSERVICEUNKNOWN);
add_macrox_name(LASTSERVICECRITICAL);
add_macrox_name(LASTHOSTUP);
add_macrox_name(LASTHOSTDOWN);
add_macrox_name(LASTHOSTUNREACHABLE);
add_macrox_name(SERVICECHECKCOMMAND);
add_macrox_name(HOSTCHECKCOMMAND);
add_macrox_name(MAINCONFIGFILE);
add_macrox_name(STATUSDATAFILE);
add_macrox_name(HOSTDISPLAYNAME);
add_macrox_name(SERVICEDISPLAYNAME);
add_macrox_name(RETENTIONDATAFILE);
add_macrox_name(OBJECTCACHEFILE);
add_macrox_name(TEMPFILE);
add_macrox_name(LOGFILE);
add_macrox_name(RESOURCEFILE);
add_macrox_name(COMMANDFILE);
add_macrox_name(HOSTPERFDATAFILE);
add_macrox_name(SERVICEPERFDATAFILE);
add_macrox_name(HOSTACTIONURL);
add_macrox_name(HOSTNOTESURL);
add_macrox_name(HOSTNOTES);
add_macrox_name(SERVICEACTIONURL);
add_macrox_name(SERVICENOTESURL);
add_macrox_name(SERVICENOTES);
add_macrox_name(TOTALHOSTSUP);
add_macrox_name(TOTALHOSTSDOWN);
add_macrox_name(TOTALHOSTSUNREACHABLE);
add_macrox_name(TOTALHOSTSDOWNUNHANDLED);
add_macrox_name(TOTALHOSTSUNREACHABLEUNHANDLED);
add_macrox_name(TOTALHOSTPROBLEMS);
add_macrox_name(TOTALHOSTPROBLEMSUNHANDLED);
add_macrox_name(TOTALSERVICESOK);
add_macrox_name(TOTALSERVICESWARNING);
add_macrox_name(TOTALSERVICESCRITICAL);
add_macrox_name(TOTALSERVICESUNKNOWN);
add_macrox_name(TOTALSERVICESWARNINGUNHANDLED);
add_macrox_name(TOTALSERVICESCRITICALUNHANDLED);
add_macrox_name(TOTALSERVICESUNKNOWNUNHANDLED);
add_macrox_name(TOTALSERVICEPROBLEMS);
add_macrox_name(TOTALSERVICEPROBLEMSUNHANDLED);
add_macrox_name(PROCESSSTARTTIME);
add_macrox_name(HOSTCHECKTYPE);
add_macrox_name(SERVICECHECKTYPE);
add_macrox_name(LONGHOSTOUTPUT);
add_macrox_name(LONGSERVICEOUTPUT);
add_macrox_name(TEMPPATH);
add_macrox_name(HOSTNOTIFICATIONNUMBER);
add_macrox_name(SERVICENOTIFICATIONNUMBER);
add_macrox_name(HOSTNOTIFICATIONID);
add_macrox_name(SERVICENOTIFICATIONID);
add_macrox_name(HOSTEVENTID);
add_macrox_name(LASTHOSTEVENTID);
add_macrox_name(SERVICEEVENTID);
add_macrox_name(LASTSERVICEEVENTID);
add_macrox_name(HOSTGROUPNAMES);
add_macrox_name(SERVICEGROUPNAMES);
add_macrox_name(HOSTACKAUTHORNAME);
add_macrox_name(HOSTACKAUTHORALIAS);
add_macrox_name(SERVICEACKAUTHORNAME);
add_macrox_name(SERVICEACKAUTHORALIAS);
add_macrox_name(MAXHOSTATTEMPTS);
add_macrox_name(MAXSERVICEATTEMPTS);
add_macrox_name(TOTALHOSTSERVICES);
add_macrox_name(TOTALHOSTSERVICESOK);
add_macrox_name(TOTALHOSTSERVICESWARNING);
add_macrox_name(TOTALHOSTSERVICESUNKNOWN);
add_macrox_name(TOTALHOSTSERVICESCRITICAL);
add_macrox_name(HOSTGROUPNOTES);
add_macrox_name(HOSTGROUPNOTESURL);
add_macrox_name(HOSTGROUPACTIONURL);
add_macrox_name(SERVICEGROUPNOTES);
add_macrox_name(SERVICEGROUPNOTESURL);
add_macrox_name(SERVICEGROUPACTIONURL);
add_macrox_name(HOSTGROUPMEMBERS);
add_macrox_name(SERVICEGROUPMEMBERS);
add_macrox_name(CONTACTGROUPNAME);
add_macrox_name(CONTACTGROUPALIAS);
add_macrox_name(CONTACTGROUPMEMBERS);
add_macrox_name(CONTACTGROUPNAMES);
add_macrox_name(NOTIFICATIONRECIPIENTS);
add_macrox_name(NOTIFICATIONAUTHOR);
add_macrox_name(NOTIFICATIONAUTHORNAME);
add_macrox_name(NOTIFICATIONAUTHORALIAS);
add_macrox_name(NOTIFICATIONCOMMENT);
add_macrox_name(EVENTSTARTTIME);
add_macrox_name(HOSTPROBLEMID);
add_macrox_name(LASTHOSTPROBLEMID);
add_macrox_name(SERVICEPROBLEMID);
add_macrox_name(LASTSERVICEPROBLEMID);
add_macrox_name(ISVALIDTIME);
add_macrox_name(NEXTVALIDTIME);
add_macrox_name(LASTHOSTSTATE);
add_macrox_name(LASTHOSTSTATEID);
add_macrox_name(LASTSERVICESTATE);
add_macrox_name(LASTSERVICESTATEID);
return OK;
}
/******************************************************************/
/********************* MACRO CLEANUP FUNCTIONS ********************/
/******************************************************************/
/* free memory associated with the macrox names */
int free_macrox_names(void) {
register int x = 0;
/* free each macro name */
for(x = 0; x < MACRO_X_COUNT; x++)
my_free(macro_x_names[x]);
return OK;
}
/* clear argv macros - used in commands */
int clear_argv_macros_r(nagios_macros *mac) {
register int x = 0;
/* command argument macros */
for(x = 0; x < MAX_COMMAND_ARGUMENTS; x++)
my_free(mac->argv[x]);
return OK;
}
int clear_argv_macros(void) {
return clear_argv_macros_r(&global_macros);
}
/*
* copies non-volatile macros from global macro_x to **dest, which
* must be large enough to hold at least MACRO_X_COUNT entries.
* We use a shortlived macro to save up on typing
*/
#define cp_macro(name) dest[MACRO_##name] = global_macros.x[MACRO_##name]
void copy_constant_macros(char **dest) {
cp_macro(ADMINEMAIL);
cp_macro(ADMINPAGER);
cp_macro(MAINCONFIGFILE);
cp_macro(STATUSDATAFILE);
cp_macro(RETENTIONDATAFILE);
cp_macro(OBJECTCACHEFILE);
cp_macro(TEMPFILE);
cp_macro(LOGFILE);
cp_macro(RESOURCEFILE);
cp_macro(COMMANDFILE);
cp_macro(HOSTPERFDATAFILE);
cp_macro(SERVICEPERFDATAFILE);
cp_macro(PROCESSSTARTTIME);
cp_macro(TEMPPATH);
cp_macro(EVENTSTARTTIME);
}
#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) {
customvariablesmember *this_customvariablesmember = NULL;
customvariablesmember *next_customvariablesmember = NULL;
register int x = 0;
for(x = 0; x < MACRO_X_COUNT; x++) {
switch(x) {
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;
}
}
/* 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;
}
int clear_volatile_macros(void) {
return clear_volatile_macros_r(&global_macros);
}
/* 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 pointers */
mac->service_ptr = NULL;
return OK;
}
int clear_service_macros(void) {
return clear_service_macros_r(&global_macros);
}
/* 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 pointers */
mac->host_ptr = NULL;
return OK;
}
int clear_host_macros(void) {
return clear_host_macros_r(&global_macros);
}
/* 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? */
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]);
/* clear pointers */
mac->hostgroup_ptr = NULL;
return OK;
}
int clear_hostgroup_macros(void) {
return clear_hostgroup_macros_r(&global_macros);
}
/* 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? */
my_free(mac->x[MACRO_SERVICEGROUPACTIONURL]);
my_free(mac->x[MACRO_SERVICEGROUPNOTESURL]);
my_free(mac->x[MACRO_SERVICEGROUPNOTES]);
/* generated */
my_free(mac->x[MACRO_SERVICEGROUPMEMBERS]);
/* clear pointers */
mac->servicegroup_ptr = NULL;
return OK;
}
int clear_servicegroup_macros(void) {
return clear_servicegroup_macros_r(&global_macros);
}
/* 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 */
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 pointers */
mac->contact_ptr = NULL;
return OK;
}
int clear_contact_macros(void) {
return clear_contact_macros_r(&global_macros);
}
/* clear contactgroup macros */
int clear_contactgroup_macros_r(nagios_macros *mac) {
my_free(mac->x[MACRO_CONTACTGROUPNAME]);
my_free(mac->x[MACRO_CONTACTGROUPALIAS]);
my_free(mac->x[MACRO_CONTACTGROUPMEMBERS]);
/* clear pointers */
mac->contactgroup_ptr = NULL;
return OK;
}
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;
for(x = MACRO_TOTALHOSTSUP; x <= MACRO_TOTALSERVICEPROBLEMSUNHANDLED; x++)
my_free(mac->x[x]);
return OK;
}
int clear_summary_macros(void) {
return clear_summary_macros_r(&global_macros);
}
/******************************************************************/
/****************** ENVIRONMENT MACRO FUNCTIONS *******************/
/******************************************************************/
#ifdef NSCORE
/* sets or unsets all macro environment variables */
int set_all_macro_environment_vars_r(nagios_macros *mac, int set) {
if(enable_environment_macros == FALSE)
return ERROR;
set_macrox_environment_vars_r(mac, set);
set_argv_macro_environment_vars_r(mac, set);
set_custom_macro_environment_vars_r(mac, set);
set_contact_address_environment_vars_r(mac, set);
return OK;
}
int set_all_macro_environment_vars(int set) {
return set_all_macro_environment_vars_r(&global_macros, set);
}
/* sets or unsets macrox environment variables */
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;
/* 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)
grab_macrox_value_r(mac, x, NULL, NULL, &mac->x[x], &free_macro);
}
/* set the value */
set_macro_environment_var(macro_x_names[x], mac->x[x], set);
}
return OK;
}
int set_macrox_environment_vars(int set) {
return set_macrox_environment_vars_r(&global_macros, set);
}
/* sets or unsets argv macro environment variables */
int set_argv_macro_environment_vars_r(nagios_macros *mac, int set) {
char *macro_name = NULL;
register int x = 0;
/* set each of the argv macro environment variables */
for(x = 0; x < MAX_COMMAND_ARGUMENTS; x++) {
asprintf(¯o_name, "ARG%d", x + 1);
set_macro_environment_var(macro_name, mac->argv[x], set);
my_free(macro_name);
}
return OK;
}
int set_argv_macro_environment_vars(int set) {
return set_argv_macro_environment_vars_r(&global_macros, set);
}
/* sets or unsets custom host/service/contact macro environment variables */
int set_custom_macro_environment_vars_r(nagios_macros *mac, int set) {
customvariablesmember *temp_customvariablesmember = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
contact *temp_contact = NULL;
char *customvarname = NULL;
/***** CUSTOM HOST VARIABLES *****/
/* generate variables and save them for later */
if((temp_host = mac->host_ptr) && set == TRUE) {
for(temp_customvariablesmember = temp_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
asprintf(&customvarname, "_HOST%s", 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) {
set_macro_environment_var(temp_customvariablesmember->variable_name, clean_macro_chars(temp_customvariablesmember->variable_value, STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS), set);
}
/***** CUSTOM SERVICE VARIABLES *****/
/* generate variables and save them for later */
if((temp_service = mac->service_ptr) && set == TRUE) {
for(temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
asprintf(&customvarname, "_SERVICE%s", 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)
set_macro_environment_var(temp_customvariablesmember->variable_name, clean_macro_chars(temp_customvariablesmember->variable_value, STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS), set);
/***** CUSTOM CONTACT VARIABLES *****/
/* generate variables and save them for later */
if((temp_contact = mac->contact_ptr) && set == TRUE) {
for(temp_customvariablesmember = temp_contact->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
asprintf(&customvarname, "_CONTACT%s", 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)
set_macro_environment_var(temp_customvariablesmember->variable_name, clean_macro_chars(temp_customvariablesmember->variable_value, STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS), set);
return OK;
}
int set_custom_macro_environment_vars(int set) {
return set_custom_macro_environment_vars_r(&global_macros, set);
}
/* sets or unsets contact address environment variables */
int set_contact_address_environment_vars_r(nagios_macros *mac, int set) {
char *varname = NULL;
register int x;
/* these only get set during notifications */
if(mac->contact_ptr == NULL)
return OK;
for(x = 0; x < MAX_CONTACT_ADDRESSES; x++) {
asprintf(&varname, "CONTACTADDRESS%d", x);
set_macro_environment_var(varname, mac->contact_ptr->address[x], set);
my_free(varname);
}
return OK;
}
int set_contact_address_environment_vars(int set) {
return set_contact_address_environment_vars_r(&global_macros, set);
}
/* sets or unsets a macro environment variable */
int set_macro_environment_var(char *name, char *value, int set) {
char *env_macro_name = NULL;
/* we won't mess with null variable names */
if(name == NULL)
return ERROR;
/* create environment var name */
asprintf(&env_macro_name, "%s%s", MACRO_ENV_VAR_PREFIX, name);
/* set or unset the environment variable */
set_environment_var(env_macro_name, value, set);
/* free allocated memory */
my_free(env_macro_name);
return OK;
}
#endif
nagios/common/objects.c 0000664 0000000 0000000 00000342323 12210155146 0015427 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* OBJECTS.C - Object addition and search functions for Nagios
*
* Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 11-30-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.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/skiplist.h"
#ifdef NSCORE
#include "../include/nagios.h"
#endif
#ifdef NSCGI
#include "../include/cgiutils.h"
#endif
/**** IMPLEMENTATION-SPECIFIC HEADER FILES ****/
#ifdef USE_XODTEMPLATE /* template-based routines */
#include "../xdata/xodtemplate.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];
#ifdef NSCORE
int __nagios_object_structure_version = CURRENT_OBJECT_STRUCTURE_VERSION;
extern int use_precached_objects;
#endif
/******************************************************************/
/******* 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 result = OK;
/* initialize object skiplists */
init_object_skiplists();
/********* 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);
if(result != OK)
return ERROR;
#endif
return result;
}
/******************************************************************/
/******************** 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;
/* 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 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;
}
int get_service_count(void) {
if(object_skiplists[SERVICE_SKIPLIST])
return object_skiplists[SERVICE_SKIPLIST]->items;
return 0;
}
/******************************************************************/
/**************** OBJECT ADDITION FUNCTIONS ***********************/
/******************************************************************/
/* add a new timeperiod to the list in memory */
timeperiod *add_timeperiod(char *name, char *alias) {
timeperiod *new_timeperiod = NULL;
int result = OK;
/* make sure we have the data we need */
if((name == NULL || !strcmp(name, "")) || (alias == NULL || !strcmp(alias, ""))) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Name or alias for timeperiod is NULL\n");
return NULL;
}
/* allocate memory for the new timeperiod */
if((new_timeperiod = calloc(1, sizeof(timeperiod))) == NULL)
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;
/* add new timeperiod to skiplist */
if(result == OK) {
result = skiplist_insert(object_skiplists[TIMEPERIOD_SKIPLIST], (void *)new_timeperiod);
switch(result) {
case SKIPLIST_ERROR_DUPLICATE:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Timeperiod '%s' has already been defined\n", name);
result = ERROR;
break;
case SKIPLIST_OK:
result = OK;
break;
default:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add timeperiod '%s' to skiplist\n", name);
result = ERROR;
break;
}
}
/* handle errors */
if(result == ERROR) {
my_free(new_timeperiod->alias);
my_free(new_timeperiod->name);
my_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;
}
return new_timeperiod;
}
/* adds a new exclusion to a timeperiod */
timeperiodexclusion *add_exclusion_to_timeperiod(timeperiod *period, char *name) {
timeperiodexclusion *new_timeperiodexclusion = NULL;
/* make sure we have enough data */
if(period == NULL || name == NULL)
return NULL;
if((new_timeperiodexclusion = (timeperiodexclusion *)malloc(sizeof(timeperiodexclusion))) == NULL)
return NULL;
new_timeperiodexclusion->timeperiod_name = (char *)strdup(name);
new_timeperiodexclusion->next = period->exclusions;
period->exclusions = new_timeperiodexclusion;
return new_timeperiodexclusion;
}
/* 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;
/* make sure we have the data we need */
if(period == NULL)
return NULL;
if(day < 0 || day > 6) {
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) {
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) {
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;
}
/* allocate memory for the new time range */
if((new_timerange = malloc(sizeof(timerange))) == NULL)
return NULL;
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;
return new_timerange;
}
/* add a new exception to a timeperiod */
daterange *add_exception_to_timeperiod(timeperiod *period, int type, int syear, int smon, int smday, int swday, int swday_offset, int eyear, int emon, int emday, int ewday, int ewday_offset, int skip_interval) {
daterange *new_daterange = NULL;
/* make sure we have the data we need */
if(period == NULL)
return NULL;
/* allocate memory for the date range range */
if((new_daterange = malloc(sizeof(daterange))) == NULL)
return NULL;
new_daterange->times = NULL;
new_daterange->next = NULL;
new_daterange->type = type;
new_daterange->syear = syear;
new_daterange->smon = smon;
new_daterange->smday = smday;
new_daterange->swday = swday;
new_daterange->swday_offset = swday_offset;
new_daterange->eyear = eyear;
new_daterange->emon = emon;
new_daterange->emday = emday;
new_daterange->ewday = ewday;
new_daterange->ewday_offset = ewday_offset;
new_daterange->skip_interval = skip_interval;
/* add the new date range to the head of the range list for this exception type */
new_daterange->next = period->exceptions[type];
period->exceptions[type] = new_daterange;
return new_daterange;
}
/* add a new timerange to a daterange */
timerange *add_timerange_to_daterange(daterange *drange, unsigned long start_time, unsigned long end_time) {
timerange *new_timerange = NULL;
/* make sure we have the data we need */
if(drange == NULL)
return NULL;
if(start_time < 0 || 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) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: End time %lu is not value for timeperiod\n", end_time);
return NULL;
}
/* allocate memory for the new time range */
if((new_timerange = malloc(sizeof(timerange))) == NULL)
return NULL;
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 date range */
new_timerange->next = drange->times;
drange->times = new_timerange;
return new_timerange;
}
/* 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 *new_host = 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");
return NULL;
}
/* check values */
if(max_attempts <= 0) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid max_check_attempts value for host '%s'\n", name);
return NULL;
}
if(check_interval < 0) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid check_interval value for host '%s'\n", name);
return NULL;
}
if(notification_interval < 0) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid notification_interval value for host '%s'\n", name);
return NULL;
}
if(first_notification_delay < 0) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid first_notification_delay value for host '%s'\n", name);
return NULL;
}
if(freshness_threshold < 0) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid freshness_threshold value for host '%s'\n", name);
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;
}
/* duplicate non-string vars */
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->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->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->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;
new_host->x_3d = x_3d;
new_host->y_3d = y_3d;
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->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->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 */
if(result == OK) {
result = skiplist_insert(object_skiplists[HOST_SKIPLIST], (void *)new_host);
switch(result) {
case SKIPLIST_ERROR_DUPLICATE:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host '%s' has already been defined\n", name);
result = ERROR;
break;
case SKIPLIST_OK:
result = OK;
break;
default:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add host '%s' to skiplist\n", name);
result = ERROR;
break;
}
}
/* 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;
}
return new_host;
}
hostsmember *add_parent_host_to_host(host *hst, char *host_name) {
hostsmember *new_hostsmember = NULL;
int result = OK;
/* make sure we have the data we need */
if(hst == NULL || host_name == NULL || !strcmp(host_name, "")) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host is NULL or parent host name is NULL\n");
return NULL;
}
/* a host cannot be a parent/child of itself */
if(!strcmp(host_name, hst->name)) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host '%s' cannot be a child/parent of itself\n", hst->name);
return NULL;
}
/* allocate memory */
if((new_hostsmember = (hostsmember *)calloc(1, sizeof(hostsmember))) == NULL)
return NULL;
/* duplicate string vars */
if((new_hostsmember->host_name = (char *)strdup(host_name)) == NULL)
result = ERROR;
/* handle errors */
if(result == ERROR) {
my_free(new_hostsmember->host_name);
my_free(new_hostsmember);
return NULL;
}
/* add the parent host entry to the host definition */
new_hostsmember->next = hst->parent_hosts;
hst->parent_hosts = new_hostsmember;
return new_hostsmember;
}
hostsmember *add_child_link_to_host(host *hst, host *child_ptr) {
hostsmember *new_hostsmember = NULL;
/* make sure we have the data we need */
if(hst == NULL || child_ptr == NULL)
return NULL;
/* allocate memory */
if((new_hostsmember = (hostsmember *)malloc(sizeof(hostsmember))) == NULL)
return NULL;
/* initialize values */
new_hostsmember->host_name = NULL;
#ifdef NSCORE
new_hostsmember->host_ptr = child_ptr;
#endif
/* add the child entry to the host definition */
new_hostsmember->next = hst->child_hosts;
hst->child_hosts = new_hostsmember;
return new_hostsmember;
}
servicesmember *add_service_link_to_host(host *hst, service *service_ptr) {
servicesmember *new_servicesmember = NULL;
/* make sure we have the data we need */
if(hst == NULL || service_ptr == NULL)
return NULL;
/* allocate memory */
if((new_servicesmember = (servicesmember *)calloc(1, sizeof(servicesmember))) == NULL)
return NULL;
/* initialize values */
#ifdef NSCORE
new_servicesmember->service_ptr = service_ptr;
#endif
/* add the child entry to the host definition */
new_servicesmember->next = hst->services;
hst->services = new_servicesmember;
return new_servicesmember;
}
/* add a new contactgroup to a host */
contactgroupsmember *add_contactgroup_to_host(host *hst, char *group_name) {
contactgroupsmember *new_contactgroupsmember = NULL;
int result = OK;
/* 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");
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);
return NULL;
}
/* add the new member to the head of the member list */
new_contactgroupsmember->next = hst->contact_groups;
hst->contact_groups = new_contactgroupsmember;;
return new_contactgroupsmember;
}
/* adds a contact to a host */
contactsmember *add_contact_to_host(host *hst, char *contact_name) {
return add_contact_to_object(&hst->contacts, contact_name);
}
/* adds a custom variable to a host */
customvariablesmember *add_custom_variable_to_host(host *hst, char *varname, char *varvalue) {
return add_custom_variable_to_object(&hst->custom_variables, varname, varvalue);
}
/* add a new host group to the list in memory */
hostgroup *add_hostgroup(char *name, char *alias, char *notes, char *notes_url, char *action_url) {
hostgroup *new_hostgroup = NULL;
int result = OK;
/* make sure we have the data we need */
if(name == NULL || !strcmp(name, "")) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Hostgroup name is NULL\n");
return NULL;
}
/* allocate memory */
if((new_hostgroup = (hostgroup *)calloc(1, sizeof(hostgroup))) == NULL)
return NULL;
/* 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;
}
/* add new host group to skiplist */
if(result == OK) {
result = skiplist_insert(object_skiplists[HOSTGROUP_SKIPLIST], (void *)new_hostgroup);
switch(result) {
case SKIPLIST_ERROR_DUPLICATE:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Hostgroup '%s' has already been defined\n", name);
result = ERROR;
break;
case SKIPLIST_OK:
result = OK;
break;
default:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add hostgroup '%s' to skiplist\n", name);
result = ERROR;
break;
}
}
/* handle errors */
if(result == ERROR) {
my_free(new_hostgroup->alias);
my_free(new_hostgroup->group_name);
my_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;
}
return new_hostgroup;
}
/* add a new host to a host group */
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;
/* 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;
}
/* 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;
/* handle errors */
if(result == ERROR) {
my_free(new_member->host_name);
my_free(new_member);
return NULL;
}
/* add the new member to the member list, sorted by host name */
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) {
new_member->next = temp_member;
if(temp_member == temp_hostgroup->members)
temp_hostgroup->members = new_member;
else
last_member->next = new_member;
break;
}
else
last_member = temp_member;
}
if(temp_hostgroup->members == NULL) {
new_member->next = NULL;
temp_hostgroup->members = new_member;
}
else if(temp_member == NULL) {
new_member->next = NULL;
last_member->next = new_member;
}
return new_member;
}
/* add a new service group to the list in memory */
servicegroup *add_servicegroup(char *name, char *alias, char *notes, char *notes_url, char *action_url) {
servicegroup *new_servicegroup = NULL;
int result = OK;
/* make sure we have the data we need */
if(name == NULL || !strcmp(name, "")) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Servicegroup name is NULL\n");
return NULL;
}
/* allocate memory */
if((new_servicegroup = (servicegroup *)calloc(1, sizeof(servicegroup))) == NULL)
return NULL;
/* 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;
}
/* add new service group to skiplist */
if(result == OK) {
result = skiplist_insert(object_skiplists[SERVICEGROUP_SKIPLIST], (void *)new_servicegroup);
switch(result) {
case SKIPLIST_ERROR_DUPLICATE:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Servicegroup '%s' has already been defined\n", name);
result = ERROR;
break;
case SKIPLIST_OK:
result = OK;
break;
default:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add servicegroup '%s' to skiplist\n", name);
result = ERROR;
break;
}
}
/* 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;
}
return new_servicegroup;
}
/* add a new service to a service group */
servicesmember *add_service_to_servicegroup(servicegroup *temp_servicegroup, char *host_name, char *svc_description) {
servicesmember *new_member = NULL;
servicesmember *last_member = NULL;
servicesmember *temp_member = NULL;
int result = OK;
/* 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;
}
/* 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;
/* handle errors */
if(result == ERROR) {
my_free(new_member->service_description);
my_free(new_member->host_name);
my_free(new_member);
return NULL;
}
/* add new member to member list, sorted by host name then service description */
last_member = temp_servicegroup->members;
for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) {
if(strcmp(new_member->host_name, temp_member->host_name) < 0) {
new_member->next = temp_member;
if(temp_member == temp_servicegroup->members)
temp_servicegroup->members = new_member;
else
last_member->next = new_member;
break;
}
else if(strcmp(new_member->host_name, temp_member->host_name) == 0 && strcmp(new_member->service_description, temp_member->service_description) < 0) {
new_member->next = temp_member;
if(temp_member == temp_servicegroup->members)
temp_servicegroup->members = new_member;
else
last_member->next = new_member;
break;
}
else
last_member = temp_member;
}
if(temp_servicegroup->members == NULL) {
new_member->next = NULL;
temp_servicegroup->members = new_member;
}
else if(temp_member == NULL) {
new_member->next = NULL;
last_member->next = new_member;
}
return new_member;
}
/* 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 *new_contact = NULL;
int x = 0;
int result = OK;
/* make sure we have the data we need */
if(name == NULL || !strcmp(name, "")) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact name is NULL\n");
return NULL;
}
/* allocate memory for a new contact */
if((new_contact = (contact *)calloc(1, sizeof(contact))) == NULL)
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;
}
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;
}
}
}
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->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 */
if(result == OK) {
result = skiplist_insert(object_skiplists[CONTACT_SKIPLIST], (void *)new_contact);
switch(result) {
case SKIPLIST_ERROR_DUPLICATE:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact '%s' has already been defined\n", name);
result = ERROR;
break;
case SKIPLIST_OK:
result = OK;
break;
default:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add contact '%s' to skiplist\n", name);
result = ERROR;
break;
}
}
/* 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);
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;
}
return new_contact;
}
/* adds a host notification command to a contact definition */
commandsmember *add_host_notification_command_to_contact(contact *cntct, char *command_name) {
commandsmember *new_commandsmember = NULL;
int result = OK;
/* make sure we have the data we need */
if(cntct == NULL || (command_name == NULL || !strcmp(command_name, ""))) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact or host notification command is NULL\n");
return NULL;
}
/* allocate memory */
if((new_commandsmember = calloc(1, sizeof(commandsmember))) == NULL)
return NULL;
/* duplicate vars */
if((new_commandsmember->command = (char *)strdup(command_name)) == NULL)
result = ERROR;
/* handle errors */
if(result == ERROR) {
my_free(new_commandsmember->command);
my_free(new_commandsmember);
return NULL;
}
/* add the notification command */
new_commandsmember->next = cntct->host_notification_commands;
cntct->host_notification_commands = new_commandsmember;
return new_commandsmember;
}
/* adds a service notification command to a contact definition */
commandsmember *add_service_notification_command_to_contact(contact *cntct, char *command_name) {
commandsmember *new_commandsmember = NULL;
int result = OK;
/* make sure we have the data we need */
if(cntct == NULL || (command_name == NULL || !strcmp(command_name, ""))) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact or service notification command is NULL\n");
return NULL;
}
/* allocate memory */
if((new_commandsmember = calloc(1, sizeof(commandsmember))) == NULL)
return NULL;
/* duplicate vars */
if((new_commandsmember->command = (char *)strdup(command_name)) == NULL)
result = ERROR;
/* handle errors */
if(result == ERROR) {
my_free(new_commandsmember->command);
my_free(new_commandsmember);
return NULL;
}
/* add the notification command */
new_commandsmember->next = cntct->service_notification_commands;
cntct->service_notification_commands = new_commandsmember;
return new_commandsmember;
}
/* adds a custom variable to a contact */
customvariablesmember *add_custom_variable_to_contact(contact *cntct, char *varname, char *varvalue) {
return add_custom_variable_to_object(&cntct->custom_variables, varname, varvalue);
}
/* add a new contact group to the list in memory */
contactgroup *add_contactgroup(char *name, char *alias) {
contactgroup *new_contactgroup = NULL;
int result = OK;
/* make sure we have the data we need */
if(name == NULL || !strcmp(name, "")) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contactgroup name is NULL\n");
return NULL;
}
/* allocate memory for a new contactgroup entry */
if((new_contactgroup = calloc(1, sizeof(contactgroup))) == NULL)
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;
/* add new contact group to skiplist */
if(result == OK) {
result = skiplist_insert(object_skiplists[CONTACTGROUP_SKIPLIST], (void *)new_contactgroup);
switch(result) {
case SKIPLIST_ERROR_DUPLICATE:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contactgroup '%s' has already been defined\n", name);
result = ERROR;
break;
case SKIPLIST_OK:
result = OK;
break;
default:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add contactgroup '%s' to skiplist\n", name);
result = ERROR;
break;
}
}
/* handle errors */
if(result == ERROR) {
my_free(new_contactgroup->alias);
my_free(new_contactgroup->group_name);
my_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;
}
return new_contactgroup;
}
/* 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;
/* make sure we have the data we need */
if(grp == NULL || (contact_name == NULL || !strcmp(contact_name, ""))) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contactgroup or contact name is NULL\n");
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;
}
/* add the new member to the head of the member list */
new_contactsmember->next = grp->members;
grp->members = new_contactsmember;
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 *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, ""))) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service description, host name, or check command is NULL\n");
return NULL;
}
/* check values */
if(max_attempts <= 0 || check_interval < 0 || retry_interval <= 0 || notification_interval < 0) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid max_attempts, check_interval, retry_interval, or notification_interval value for service '%s' on host '%s'\n", description, host_name);
return NULL;
}
if(first_notification_delay < 0) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid first_notification_delay value for service '%s' on host '%s'\n", description, host_name);
return NULL;
}
/* allocate memory */
if((new_service = (service *)calloc(1, sizeof(service))) == NULL)
return NULL;
/* duplicate vars */
if((new_service->host_name = (char *)strdup(host_name)) == NULL)
result = ERROR;
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)
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;
}
if(notes_url) {
if((new_service->notes_url = (char *)strdup(notes_url)) == NULL)
result = ERROR;
}
if(action_url) {
if((new_service->action_url = (char *)strdup(action_url)) == NULL)
result = ERROR;
}
if(icon_image) {
if((new_service->icon_image = (char *)strdup(icon_image)) == NULL)
result = ERROR;
}
if(icon_image_alt) {
if((new_service->icon_image_alt = (char *)strdup(icon_image_alt)) == NULL)
result = ERROR;
}
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->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->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->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;
#ifdef NSCORE
new_service->problem_has_been_acknowledged = FALSE;
new_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE;
new_service->check_type = SERVICE_CHECK_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 */
if(result == OK) {
result = skiplist_insert(object_skiplists[SERVICE_SKIPLIST], (void *)new_service);
switch(result) {
case SKIPLIST_ERROR_DUPLICATE:
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:
result = OK;
break;
default:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add service '%s' on host '%s' to skiplist\n", description, host_name);
result = ERROR;
break;
}
}
/* handle errors */
if(result == ERROR) {
#ifdef NSCORE
my_free(new_service->perf_data);
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->description);
my_free(new_service->host_name);
my_free(new_service->display_name);
my_free(new_service);
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;
}
return new_service;
}
/* 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;
}
/* adds a contact to a service */
contactsmember *add_contact_to_service(service *svc, char *contact_name) {
return add_contact_to_object(&svc->contacts, contact_name);
}
/* adds a custom variable to a service */
customvariablesmember *add_custom_variable_to_service(service *svc, char *varname, char *varvalue) {
return add_custom_variable_to_object(&svc->custom_variables, varname, varvalue);
}
/* add a new command to the list in memory */
command *add_command(char *name, char *value) {
command *new_command = NULL;
int result = OK;
/* make sure we have the data we need */
if((name == NULL || !strcmp(name, "")) || (value == NULL || !strcmp(value, ""))) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Command name of command line is NULL\n");
return NULL;
}
/* allocate memory for the new command */
if((new_command = (command *)calloc(1, sizeof(command))) == NULL)
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;
/* add new command to skiplist */
if(result == OK) {
result = skiplist_insert(object_skiplists[COMMAND_SKIPLIST], (void *)new_command);
switch(result) {
case SKIPLIST_ERROR_DUPLICATE:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Command '%s' has already been defined\n", name);
result = ERROR;
break;
case SKIPLIST_OK:
result = OK;
break;
default:
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add command '%s' to skiplist\n", name);
result = ERROR;
break;
}
}
/* 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;
}
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 *new_serviceescalation = NULL;
int result = OK;
/* make sure we have the data we need */
if((host_name == NULL || !strcmp(host_name, "")) || (description == NULL || !strcmp(description, ""))) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service escalation host name or description is NULL\n");
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)
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;
}
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;
}
return new_serviceescalation;
}
/* 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;
}
/* adds a contact to a service escalation */
contactsmember *add_contact_to_serviceescalation(serviceescalation *se, char *contact_name) {
return add_contact_to_object(&se->contacts, contact_name);
}
/* 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 *new_servicedependency = NULL;
int result = OK;
/* 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");
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");
return NULL;
}
/* allocate memory for a new service dependency entry */
if((new_servicedependency = (servicedependency *)calloc(1, sizeof(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->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
/* 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;
}
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 *new_hostdependency = NULL;
int result = OK;
/* 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");
return NULL;
}
/* allocate memory for a new host dependency entry */
if((new_hostdependency = (hostdependency *)calloc(1, sizeof(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->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
/* 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;
}
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 *new_hostescalation = NULL;
int result = OK;
/* make sure we have the data we need */
if(host_name == NULL || !strcmp(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)
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->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;
}
return new_hostescalation;
}
/* 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;
}
/* adds a contact to a host escalation */
contactsmember *add_contact_to_hostescalation(hostescalation *he, char *contact_name) {
return add_contact_to_object(&he->contacts, contact_name);
}
/* adds a contact to an object */
contactsmember *add_contact_to_object(contactsmember **object_ptr, char *contactname) {
contactsmember *new_contactsmember = NULL;
/* make sure we have the data we need */
if(object_ptr == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact object is NULL\n");
return NULL;
}
if(contactname == NULL || !strcmp(contactname, "")) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact name is NULL\n");
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;
}
/* set initial values */
#ifdef NSCORE
new_contactsmember->contact_ptr = NULL;
#endif
/* add the new contact to the head of the contact list */
new_contactsmember->next = *object_ptr;
*object_ptr = new_contactsmember;
return new_contactsmember;
}
/* adds a custom variable to an object */
customvariablesmember *add_custom_variable_to_object(customvariablesmember **object_ptr, char *varname, char *varvalue) {
customvariablesmember *new_customvariablesmember = NULL;
/* make sure we have the data we need */
if(object_ptr == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Custom variable object is NULL\n");
return NULL;
}
if(varname == NULL || !strcmp(varname, "")) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Custom variable name is NULL\n");
return NULL;
}
/* allocate memory for a new member */
if((new_customvariablesmember = malloc(sizeof(customvariablesmember))) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not allocate memory for custom variable\n");
return NULL;
}
if((new_customvariablesmember->variable_name = (char *)strdup(varname)) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not allocate memory for custom variable name\n");
my_free(new_customvariablesmember);
return NULL;
}
if(varvalue) {
if((new_customvariablesmember->variable_value = (char *)strdup(varvalue)) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not allocate memory for custom variable value\n");
my_free(new_customvariablesmember->variable_name);
my_free(new_customvariablesmember);
return NULL;
}
}
else
new_customvariablesmember->variable_value = NULL;
/* set initial values */
new_customvariablesmember->has_been_modified = FALSE;
/* add the new member to the head of the member list */
new_customvariablesmember->next = *object_ptr;
*object_ptr = new_customvariablesmember;
return new_customvariablesmember;
}
/******************************************************************/
/******************** 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);
}
/* 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);
}
/* 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);
}
/* 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);
}
/* 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);
}
/* 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);
}
/* 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);
}
/* 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);
}
/******************************************************************/
/******************* 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;
objectlist *new_item = NULL;
if(list == NULL || object_ptr == NULL)
return ERROR;
/* skip this object if its already in the list */
for(temp_item = *list; temp_item; temp_item = temp_item->next) {
if(temp_item->object_ptr == object_ptr)
break;
}
if(temp_item)
return OK;
/* allocate memory for a new list item */
if((new_item = (objectlist *)malloc(sizeof(objectlist))) == NULL)
return ERROR;
/* initialize vars */
new_item->object_ptr = object_ptr;
/* add new item to head of list */
new_item->next = *list;
*list = new_item;
return OK;
}
/* frees memory allocated to a temporary object list */
int free_objectlist(objectlist **temp_list) {
objectlist *this_objectlist = NULL;
objectlist *next_objectlist = NULL;
if(temp_list == NULL)
return ERROR;
/* free memory allocated to object list */
for(this_objectlist = *temp_list; this_objectlist != NULL; this_objectlist = next_objectlist) {
next_objectlist = this_objectlist->next;
my_free(this_objectlist);
}
*temp_list = NULL;
return OK;
}
#endif
/******************************************************************/
/********************* OBJECT QUERY FUNCTIONS *********************/
/******************************************************************/
/* determines whether or not a specific host is an immediate child of another host */
int is_host_immediate_child_of_host(host *parent_host, host *child_host) {
hostsmember *temp_hostsmember = NULL;
/* not enough data */
if(child_host == NULL)
return FALSE;
/* root/top-level hosts */
if(parent_host == NULL) {
if(child_host->parent_hosts == NULL)
return TRUE;
}
/* mid-level/bottom hosts */
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
}
}
return FALSE;
}
/* determines whether or not a specific host is an immediate parent of another host */
int is_host_immediate_parent_of_host(host *child_host, host *parent_host) {
if(is_host_immediate_child_of_host(parent_host, child_host) == TRUE)
return TRUE;
return FALSE;
}
/* returns a count of the immediate children for a given host */
/* NOTE: This function is only used by the CGIS */
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++;
}
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;
}
return children;
}
/* get the number of immediate parent hosts for a given host */
/* NOTE: This function is only used by the CGIS */
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++;
}
}
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;
}
}
return parents;
}
/* tests whether a host is a member of a particular hostgroup */
/* NOTE: This function is only used by the CGIS */
int is_host_member_of_hostgroup(hostgroup *group, host *hst) {
hostsmember *temp_hostsmember = NULL;
if(group == NULL || hst == NULL)
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;
}
/* tests whether a host is a member of a particular servicegroup */
/* NOTE: This function is only used by the CGIS */
int is_host_member_of_servicegroup(servicegroup *group, host *hst) {
servicesmember *temp_servicesmember = NULL;
if(group == NULL || hst == NULL)
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;
}
/* tests whether a service is a member of a particular servicegroup */
/* NOTE: This function is only used by the CGIS */
int is_service_member_of_servicegroup(servicegroup *group, service *svc) {
servicesmember *temp_servicesmember = NULL;
if(group == NULL || svc == NULL)
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;
}
/*
* tests whether a contact is a member of a particular contactgroup.
* The mk-livestatus eventbroker module uses this, so it must hang
* around until 4.0 to prevent api breakage.
* The cgi's stopped using it quite long ago though, so we need only
* compile it if we're building the core
*/
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)
return TRUE;
}
return FALSE;
}
/* 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;
if(hst == NULL || cntct == NULL) {
return FALSE;
}
/* 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)
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;
}
return FALSE;
}
/* 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;
contactgroupsmember *temp_contactgroupsmember = NULL;
contactgroup *temp_contactgroup = NULL;
void *ptr = NULL;
/* 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;
}
}
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;
if(svc == NULL || cntct == NULL)
return FALSE;
/* 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)
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;
}
return FALSE;
}
/* tests whether or not 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;
/* 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)) {
/* 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;
}
}
return FALSE;
}
#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;
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;
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)
return TRUE;
}
return FALSE;
}
/* 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)
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;
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
/******************************************************************/
/******************* OBJECT DELETION FUNCTIONS ********************/
/******************************************************************/
/* 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;
/**** free memory for the timeperiod list ****/
this_timeperiod = timeperiod_list;
while(this_timeperiod != NULL) {
/* free the exception time ranges contained in this timeperiod */
for(x = 0; x < DATERANGE_TYPES; x++) {
for(this_daterange = this_timeperiod->exceptions[x]; this_daterange != NULL; this_daterange = next_daterange) {
next_daterange = this_daterange->next;
for(this_timerange = this_daterange->times; this_timerange != NULL; this_timerange = next_timerange) {
next_timerange = this_timerange->next;
my_free(this_timerange);
}
my_free(this_daterange);
}
}
/* free the day time ranges contained in this timeperiod */
for(x = 0; x < 7; x++) {
for(this_timerange = this_timeperiod->days[x]; this_timerange != NULL; this_timerange = next_timerange) {
next_timerange = this_timerange->next;
my_free(this_timerange);
}
}
/* free exclusions */
for(this_timeperiodexclusion = this_timeperiod->exclusions; this_timeperiodexclusion != NULL; this_timeperiodexclusion = next_timeperiodexclusion) {
next_timeperiodexclusion = this_timeperiodexclusion->next;
my_free(this_timeperiodexclusion->timeperiod_name);
my_free(this_timeperiodexclusion);
}
next_timeperiod = this_timeperiod->next;
my_free(this_timeperiod->name);
my_free(this_timeperiod->alias);
my_free(this_timeperiod);
this_timeperiod = next_timeperiod;
}
/* reset pointers */
timeperiod_list = NULL;
/**** free memory for the host list ****/
this_host = host_list;
while(this_host != NULL) {
next_host = this_host->next;
/* free memory for parent hosts */
this_hostsmember = this_host->parent_hosts;
while(this_hostsmember != NULL) {
next_hostsmember = this_hostsmember->next;
my_free(this_hostsmember->host_name);
my_free(this_hostsmember);
this_hostsmember = next_hostsmember;
}
/* free memory for child host links */
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;
}
/* free memory for service links */
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;
}
/* free memory for contact groups */
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;
}
/* free memory for contacts */
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;
}
/* free memory for custom variables */
this_customvariablesmember = this_host->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_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);
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);
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);
my_free(this_host);
this_host = next_host;
}
/* reset pointers */
host_list = NULL;
/**** free memory for the host group list ****/
this_hostgroup = hostgroup_list;
while(this_hostgroup != NULL) {
/* 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;
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;
/**** free memory for the service group list ****/
this_servicegroup = servicegroup_list;
while(this_servicegroup != NULL) {
/* 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;
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;
/**** free memory for the contact list ****/
this_contact = contact_list;
while(this_contact != NULL) {
/* free memory for the host notification commands */
this_commandsmember = this_contact->host_notification_commands;
while(this_commandsmember != NULL) {
next_commandsmember = this_commandsmember->next;
if(this_commandsmember->command != NULL)
my_free(this_commandsmember->command);
my_free(this_commandsmember);
this_commandsmember = next_commandsmember;
}
/* free memory for the service notification commands */
this_commandsmember = this_contact->service_notification_commands;
while(this_commandsmember != NULL) {
next_commandsmember = this_commandsmember->next;
if(this_commandsmember->command != NULL)
my_free(this_commandsmember->command);
my_free(this_commandsmember);
this_commandsmember = next_commandsmember;
}
/* free memory for custom variables */
this_customvariablesmember = this_contact->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_contact = this_contact->next;
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);
#ifdef NSCORE
free_objectlist(&this_contact->contactgroups_ptr);
#endif
my_free(this_contact);
this_contact = next_contact;
}
/* reset pointers */
contact_list = NULL;
/**** free memory for the contact group list ****/
this_contactgroup = contactgroup_list;
while(this_contactgroup != NULL) {
/* 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;
my_free(this_contactgroup->group_name);
my_free(this_contactgroup->alias);
my_free(this_contactgroup);
this_contactgroup = next_contactgroup;
}
/* reset pointers */
contactgroup_list = NULL;
/**** free memory for the service list ****/
this_service = service_list;
while(this_service != NULL) {
next_service = this_service->next;
/* 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;
}
/* free memory for contacts */
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;
}
/* free memory for 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->host_name);
my_free(this_service->description);
my_free(this_service->display_name);
my_free(this_service->service_check_command);
#ifdef NSCORE
my_free(this_service->plugin_output);
my_free(this_service->long_plugin_output);
my_free(this_service->perf_data);
my_free(this_service->event_handler_args);
my_free(this_service->check_command_args);
free_objectlist(&this_service->servicegroups_ptr);
#endif
my_free(this_service->notification_period);
my_free(this_service->check_period);
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;
/**** free memory for the command list ****/
this_command = command_list;
while(this_command != NULL) {
next_command = this_command->next;
my_free(this_command->name);
my_free(this_command->command_line);
my_free(this_command);
this_command = next_command;
}
/* reset pointers */
command_list = NULL;
/**** free memory for the service escalation list ****/
this_serviceescalation = serviceescalation_list;
while(this_serviceescalation != NULL) {
/* 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;
}
/* free memory for contacts */
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;
/**** 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;
}
/* 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;
}
/* reset pointers */
hostdependency_list = NULL;
/**** free memory for the host escalation list ****/
this_hostescalation = hostescalation_list;
while(this_hostescalation != NULL) {
/* 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;
}
/* free memory for contacts */
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;
/* free object skiplists */
free_object_skiplists();
return OK;
}
nagios/common/shared.c 0000664 0000000 0000000 00000027533 12210155146 0015247 0 ustar 00root root 0000000 0000000 #include "../include/config.h"
#include "../include/common.h"
/*
* This file holds random utility functions shared by cgi's and
* core.
*/
extern int date_format;
/* fix the problem with strtok() skipping empty options between tokens */
char *my_strtok(char *buffer, char *tokens) {
char *token_position = NULL;
char *sequence_head = NULL;
static char *my_strtok_buffer = NULL;
static char *original_my_strtok_buffer = NULL;
if(buffer != NULL) {
my_free(original_my_strtok_buffer);
if((my_strtok_buffer = (char *)strdup(buffer)) == NULL)
return NULL;
original_my_strtok_buffer = my_strtok_buffer;
}
sequence_head = my_strtok_buffer;
if(sequence_head[0] == '\x0')
return NULL;
token_position = strchr(my_strtok_buffer, tokens[0]);
if(token_position == NULL) {
my_strtok_buffer = strchr(my_strtok_buffer, '\x0');
return sequence_head;
}
token_position[0] = '\x0';
my_strtok_buffer = token_position + 1;
return sequence_head;
}
/* fixes compiler problems under Solaris, since strsep() isn't included */
/* this code is taken from the glibc source */
char *my_strsep(char **stringp, const char *delim) {
char *begin, *end;
begin = *stringp;
if(begin == NULL)
return NULL;
/* A frequent case is when the delimiter string contains only one
* character. Here we don't need to call the expensive `strpbrk'
* function and instead work using `strchr'. */
if(delim[0] == '\0' || delim[1] == '\0') {
char ch = delim[0];
if(ch == '\0' || begin[0] == '\0')
end = NULL;
else {
if(*begin == ch)
end = begin;
else
end = strchr(begin + 1, ch);
}
}
else {
/* find the end of the token. */
end = strpbrk(begin, delim);
}
if(end) {
/* terminate the token and set *STRINGP past NUL character. */
*end++ = '\0';
*stringp = end;
}
else
/* no more delimiters; this is the last token. */
*stringp = NULL;
return begin;
}
/* open a file read-only via mmap() */
mmapfile *mmap_fopen(char *filename) {
mmapfile *new_mmapfile = NULL;
int fd = 0;
void *mmap_buf = NULL;
struct stat statbuf;
int mode = O_RDONLY;
unsigned long file_size = 0L;
if(filename == NULL)
return NULL;
/* allocate memory */
if((new_mmapfile = (mmapfile *) malloc(sizeof(mmapfile))) == NULL)
return NULL;
/* open the file */
if((fd = open(filename, mode)) == -1) {
my_free(new_mmapfile);
return NULL;
}
/* get file info */
if((fstat(fd, &statbuf)) == -1) {
close(fd);
my_free(new_mmapfile);
return NULL;
}
/* get file size */
file_size = (unsigned long)statbuf.st_size;
/* only mmap() if we have a file greater than 0 bytes */
if(file_size > 0) {
/* mmap() the file - allocate one extra byte for processing zero-byte files */
if((mmap_buf =
(void *)mmap(0, file_size, PROT_READ, MAP_PRIVATE, fd,
0)) == MAP_FAILED) {
close(fd);
my_free(new_mmapfile);
return NULL;
}
}
else
mmap_buf = NULL;
/* populate struct info for later use */
new_mmapfile->path = (char *)strdup(filename);
new_mmapfile->fd = fd;
new_mmapfile->file_size = (unsigned long)file_size;
new_mmapfile->current_position = 0L;
new_mmapfile->current_line = 0L;
new_mmapfile->mmap_buf = mmap_buf;
return new_mmapfile;
}
/* close a file originally opened via mmap() */
int mmap_fclose(mmapfile * temp_mmapfile) {
if(temp_mmapfile == NULL)
return ERROR;
/* un-mmap() the file */
if(temp_mmapfile->file_size > 0L)
munmap(temp_mmapfile->mmap_buf, temp_mmapfile->file_size);
/* close the file */
close(temp_mmapfile->fd);
/* free memory */
my_free(temp_mmapfile->path);
my_free(temp_mmapfile);
return OK;
}
/* gets one line of input from an mmap()'ed file */
char *mmap_fgets(mmapfile * temp_mmapfile) {
char *buf = NULL;
unsigned long x = 0L;
int len = 0;
if(temp_mmapfile == NULL)
return NULL;
/* size of file is 0 bytes */
if(temp_mmapfile->file_size == 0L)
return NULL;
/* we've reached the end of the file */
if(temp_mmapfile->current_position >= temp_mmapfile->file_size)
return NULL;
/* find the end of the string (or buffer) */
for(x = temp_mmapfile->current_position; x < temp_mmapfile->file_size;
x++) {
if(*((char *)(temp_mmapfile->mmap_buf) + x) == '\n') {
x++;
break;
}
}
/* calculate length of line we just read */
len = (int)(x - temp_mmapfile->current_position);
/* allocate memory for the new line */
if((buf = (char *)malloc(len + 1)) == NULL)
return NULL;
/* copy string to newly allocated memory and terminate the string */
memcpy(buf,
((char *)(temp_mmapfile->mmap_buf) +
temp_mmapfile->current_position), len);
buf[len] = '\x0';
/* update the current position */
temp_mmapfile->current_position = x;
/* increment the current line */
temp_mmapfile->current_line++;
return buf;
}
/* gets one line of input from an mmap()'ed file (may be contained on more than one line in the source file) */
char *mmap_fgets_multiline(mmapfile * temp_mmapfile) {
char *buf = NULL;
char *tempbuf = NULL;
char *stripped = NULL;
int len = 0;
int len2 = 0;
int end = 0;
if(temp_mmapfile == NULL)
return NULL;
while(1) {
my_free(tempbuf);
if((tempbuf = mmap_fgets(temp_mmapfile)) == NULL)
break;
if(buf == NULL) {
len = strlen(tempbuf);
if((buf = (char *)malloc(len + 1)) == NULL)
break;
memcpy(buf, tempbuf, len);
buf[len] = '\x0';
}
else {
/* strip leading white space from continuation lines */
stripped = tempbuf;
while(*stripped == ' ' || *stripped == '\t')
stripped++;
len = strlen(stripped);
len2 = strlen(buf);
if((buf =
(char *)realloc(buf, len + len2 + 1)) == NULL)
break;
strcat(buf, stripped);
len += len2;
buf[len] = '\x0';
}
if(len == 0)
break;
/* handle Windows/DOS CR/LF */
if(len >= 2 && buf[len - 2] == '\r')
end = len - 3;
/* normal Unix LF */
else if(len >= 1 && buf[len - 1] == '\n')
end = len - 2;
else
end = len - 1;
/* two backslashes found. unescape first backslash first and break */
if(end >= 1 && buf[end - 1] == '\\' && buf[end] == '\\') {
buf[end] = '\n';
buf[end + 1] = '\x0';
break;
}
/* one backslash found. continue reading the next line */
else if(end > 0 && buf[end] == '\\')
buf[end] = '\x0';
/* no continuation marker was found, so break */
else
break;
}
my_free(tempbuf);
return buf;
}
/* strip newline, carriage return, and tab characters from beginning and end of a string */
void strip(char *buffer) {
register int x, z;
int len;
if(buffer == NULL || buffer[0] == '\x0')
return;
/* strip end of string */
len = (int)strlen(buffer);
for(x = len - 1; x >= 0; x--) {
switch(buffer[x]) {
case ' ':
case '\n':
case '\r':
case '\t':
buffer[x] = '\x0';
continue;
}
break;
}
/* if we stripped all of it, just return */
if(!x)
return;
/* save last position for later... */
z = x;
/* strip beginning of string (by shifting) */
/* NOTE: this is very expensive to do, so avoid it whenever possible */
for(x = 0;; x++) {
switch(buffer[x]) {
case ' ':
case '\n':
case '\r':
case '\t':
continue;
}
break;
}
if(x > 0 && z > 0) {
/* new length of the string after we stripped the end */
len = z + 1;
/* shift chars towards beginning of string to remove leading whitespace */
for(z = x; z < len; z++)
buffer[z - x] = buffer[z];
buffer[len - x] = '\x0';
}
}
/**************************************************
*************** HASH FUNCTIONS *******************
**************************************************/
/* dual hash function */
int hashfunc(const char *name1, const char *name2, int hashslots) {
unsigned int i, result;
result = 0;
if(name1)
for(i = 0; i < strlen(name1); i++)
result += name1[i];
if(name2)
for(i = 0; i < strlen(name2); i++)
result += name2[i];
result = result % hashslots;
return result;
}
/* dual hash data comparison */
int compare_hashdata(const char *val1a, const char *val1b, const char *val2a,
const char *val2b) {
int result = 0;
/* NOTE: If hash calculation changes, update the compare_strings() function! */
/* 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;
}
/*
* given a date/time in time_t format, produce a corresponding
* date/time string, including timezone
*/
void get_datetime_string(time_t * raw_time, char *buffer, int buffer_length,
int type) {
time_t t;
struct tm *tm_ptr, tm_s;
int hour;
int minute;
int second;
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",
"Oct", "Nov", "Dec"
};
char *tzone = "";
if(raw_time == NULL)
time(&t);
else
t = *raw_time;
if(type == HTTP_DATE_TIME)
tm_ptr = gmtime_r(&t, &tm_s);
else
tm_ptr = localtime_r(&t, &tm_s);
hour = tm_ptr->tm_hour;
minute = tm_ptr->tm_min;
second = tm_ptr->tm_sec;
month = tm_ptr->tm_mon + 1;
day = tm_ptr->tm_mday;
year = tm_ptr->tm_year + 1900;
#ifdef HAVE_TM_ZONE
tzone = (char *)(tm_ptr->tm_zone);
#else
tzone = (tm_ptr->tm_isdst) ? tzname[1] : tzname[0];
#endif
/* ctime() style date/time */
if(type == LONG_DATE_TIME)
snprintf(buffer, buffer_length, "%s %s %d %02d:%02d:%02d %s %d",
weekdays[tm_ptr->tm_wday], months[tm_ptr->tm_mon], day,
hour, minute, second, tzone, year);
/* short date/time */
else if(type == SHORT_DATE_TIME) {
if(date_format == DATE_FORMAT_EURO)
snprintf(buffer, buffer_length,
"%02d-%02d-%04d %02d:%02d:%02d", day, month,
year, hour, minute, second);
else if(date_format == DATE_FORMAT_ISO8601
|| date_format == DATE_FORMAT_STRICT_ISO8601)
snprintf(buffer, buffer_length,
"%04d-%02d-%02d%c%02d:%02d:%02d", year, month,
day,
(date_format ==
DATE_FORMAT_STRICT_ISO8601) ? 'T' : ' ', hour,
minute, second);
else
snprintf(buffer, buffer_length,
"%02d-%02d-%04d %02d:%02d:%02d", month, day,
year, hour, minute, second);
}
/* short date */
else if(type == SHORT_DATE) {
if(date_format == DATE_FORMAT_EURO)
snprintf(buffer, buffer_length, "%02d-%02d-%04d", day,
month, year);
else if(date_format == DATE_FORMAT_ISO8601
|| date_format == DATE_FORMAT_STRICT_ISO8601)
snprintf(buffer, buffer_length, "%04d-%02d-%02d", year,
month, day);
else
snprintf(buffer, buffer_length, "%02d-%02d-%04d", month,
day, year);
}
/* expiration date/time for HTTP headers */
else if(type == HTTP_DATE_TIME)
snprintf(buffer, buffer_length,
"%s, %02d %s %d %02d:%02d:%02d GMT",
weekdays[tm_ptr->tm_wday], day, months[tm_ptr->tm_mon],
year, hour, minute, second);
/* short time */
else
snprintf(buffer, buffer_length, "%02d:%02d:%02d", hour, minute,
second);
buffer[buffer_length - 1] = '\x0';
}
/* get days, hours, minutes, and seconds from a raw time_t format or total seconds */
void get_time_breakdown(unsigned long raw_time, int *days, int *hours,
int *minutes, int *seconds) {
unsigned long temp_time;
int temp_days;
int temp_hours;
int temp_minutes;
int temp_seconds;
temp_time = raw_time;
temp_days = temp_time / 86400;
temp_time -= (temp_days * 86400);
temp_hours = temp_time / 3600;
temp_time -= (temp_hours * 3600);
temp_minutes = temp_time / 60;
temp_time -= (temp_minutes * 60);
temp_seconds = (int)temp_time;
*days = temp_days;
*hours = temp_hours;
*minutes = temp_minutes;
*seconds = temp_seconds;
}
nagios/common/skiplist.c 0000664 0000000 0000000 00000031175 12210155146 0015640 0 ustar 00root root 0000000 0000000 /************************************************************************
*
* SKIPLIST.C - Skiplist functions for use in Nagios event/object lists
*
* Copyright (c) 2008 Ethan Galstad
* Last Modified: 02-28-2008
*
* Notes:
*
* These function implement a slightly modified skiplist from that
* described by William Pugh (ftp://ftp.cs.umd.edu/pub/skipLists/skiplists.pdf).
* The structures and function were modified to allow the list to act
* like a priority queue for the Nagios event list/queue(s). Multiple nodes with
* the same key value are allowed on the list to accomodate multiple events
* occurring at the same (second) point in time. Implemented peek() and pop()
* functions to allow for quick event queue processing, and a method to delete
* a specific list item, based on its pointer, rather than its data value. Again,
* this is useful for the Nagios event queue.
*
* 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/skiplist.h"
skiplist *skiplist_new(int max_levels, float level_probability, int allow_duplicates, int append_duplicates, int (*compare_function)(void *, void *)) {
skiplist *newlist = NULL;
/* alloc memory for new list structure */
if((newlist = (skiplist *)malloc(sizeof(skiplist)))) {
/* initialize levels, etc. */
newlist->current_level = 0;
newlist->max_levels = max_levels;
newlist->level_probability = level_probability;
newlist->allow_duplicates = allow_duplicates;
newlist->append_duplicates = append_duplicates;
newlist->items = 0;
newlist->compare_function = compare_function;
/* initialize head node */
newlist->head = skiplist_new_node(newlist, max_levels);
}
return newlist;
}
int skiplist_insert(skiplist *list, void *data) {
skiplistnode **update = NULL;
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
skiplistnode *newnode = NULL;
int level = 0;
int x = 0;
if(list == NULL || data == NULL) {
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) {
if(skiplist_find_first(list, data, NULL))
return SKIPLIST_ERROR_DUPLICATE;
}
/* find proper position for insert, remember pointers with an update vector */
thisnode = list->head;
for(level = list->current_level; level >= 0; level--) {
while((nextnode = thisnode->forward[level])) {
if(list->append_duplicates == TRUE) {
if(list->compare_function(nextnode->data, data) > 0)
break;
}
else {
if(list->compare_function(nextnode->data, data) >= 0)
break;
}
thisnode = nextnode;
}
update[level] = thisnode;
}
/* 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) {
/*printf("NEW LEVEL!\n");*/
list->current_level++;
level = list->current_level;
update[level] = list->head;
}
/* create a new node */
if((newnode = skiplist_new_node(list, level)) == NULL) {
/*printf("NODE ERROR\n");*/
free(update);
return SKIPLIST_ERROR_MEMORY;
}
newnode->data = data;
/* update pointers to insert node at proper location */
do {
thisnode = update[level];
newnode->forward[level] = thisnode->forward[level];
thisnode->forward[level] = newnode;
}
while(--level >= 0);
/* update counters */
list->items++;
/* free memory */
free(update);
return SKIPLIST_OK;
}
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;
int level = 0;
if(list == NULL)
return ERROR;
/* free all list nodes (but not header) */
for(this = list->head->forward[0]; this != NULL; this = next) {
next = this->forward[0];
free(this);
}
/* reset level pointers */
for(level = list->current_level; level >= 0; level--)
list->head->forward[level] = NULL;
/* reset list level */
list->current_level = 0;
/* reset items */
list->items = 0;
return OK;
}
int skiplist_free(skiplist **list) {
skiplistnode *this = NULL;
skiplistnode *next = NULL;
if(list == NULL)
return ERROR;
if(*list == NULL)
return OK;
/* free header and all list nodes */
for(this = (*list)->head; this != NULL; this = next) {
next = this->forward[0];
free(this);
}
/* free list structure */
free(*list);
*list = NULL;
return OK;
}
/* get first item in list */
void *skiplist_peek(skiplist *list) {
if(list == NULL)
return NULL;
/* return first item */
return list->head->forward[0]->data;
}
/* get/remove first item in list */
void *skiplist_pop(skiplist *list) {
skiplistnode *thisnode = NULL;
void *data = NULL;
int level = 0;
if(list == NULL)
return NULL;
/* get first item */
thisnode = list->head->forward[0];
if(thisnode == NULL)
return NULL;
/* get data for first item */
data = thisnode->data;
/* remove first item from queue - update forward links from head to first node */
for(level = 0; level <= list->current_level; level++) {
if(list->head->forward[level] == thisnode)
list->head->forward[level] = thisnode->forward[level];
}
/* free deleted node */
free(thisnode);
/* adjust items */
list->items--;
return data;
}
/* get first item in list */
void *skiplist_get_first(skiplist *list, void **node_ptr) {
skiplistnode *thisnode = NULL;
if(list == NULL)
return NULL;
/* get first node */
thisnode = list->head->forward[0];
/* return pointer to node */
if(node_ptr)
*node_ptr = (void *)thisnode;
if(thisnode)
return thisnode->data;
else
return NULL;
}
/* get next item in list */
void *skiplist_get_next(void **node_ptr) {
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
if(node_ptr == NULL || *node_ptr == NULL)
return NULL;
thisnode = (skiplistnode *)(*node_ptr);
nextnode = thisnode->forward[0];
*node_ptr = (void *)nextnode;
if(nextnode)
return nextnode->data;
else
return NULL;
}
/* first first item in list */
void *skiplist_find_first(skiplist *list, void *data, void **node_ptr) {
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
int level = 0;
if(list == NULL || data == NULL)
return NULL;
thisnode = list->head;
for(level = list->current_level; level >= 0; level--) {
while((nextnode = thisnode->forward[level])) {
if(list->compare_function(nextnode->data, data) >= 0)
break;
thisnode = nextnode;
}
}
/* we found it! */
if(nextnode && list->compare_function(nextnode->data, data) == 0) {
if(node_ptr)
*node_ptr = (void *)nextnode;
return nextnode->data;
}
else {
if(node_ptr)
*node_ptr = NULL;
}
return NULL;
}
/* find next match */
void *skiplist_find_next(skiplist *list, void *data, void **node_ptr) {
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
if(list == NULL || data == NULL || node_ptr == NULL)
return NULL;
if(*node_ptr == NULL)
return NULL;
thisnode = (skiplistnode *)(*node_ptr);
nextnode = thisnode->forward[0];
if(nextnode) {
if(list->compare_function(nextnode->data, data) == 0) {
*node_ptr = (void *)nextnode;
return nextnode->data;
}
}
*node_ptr = NULL;
return NULL;
}
/* 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;
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
int level = 0;
int top_level = 0;
int deleted = FALSE;
int x = 0;
if(list == NULL || data == NULL)
return ERROR;
/* initialize update vector */
if((update = (skiplistnode **)malloc(sizeof(skiplistnode *) * list->max_levels)) == NULL)
return ERROR;
for(x = 0; x < list->max_levels; x++)
update[x] = NULL;
/* find location in list */
thisnode = list->head;
for(top_level = level = list->current_level; level >= 0; level--) {
while((nextnode = thisnode->forward[level])) {
if(list->compare_function(nextnode->data, data) >= 0)
break;
thisnode = nextnode;
}
update[level] = thisnode;
}
/* we found a match! */
if(list->compare_function(nextnode->data, data) == 0) {
/* adjust level pointers to bypass (soon to be) removed node */
for(level = 0; level <= top_level; level++) {
thisnode = update[level];
if(thisnode->forward[level] != nextnode)
break;
thisnode->forward[level] = nextnode->forward[level];
}
/* free node memory */
free(nextnode);
/* adjust top/current level of list is necessary */
while(list->head->forward[top_level] == NULL && top_level > 0)
top_level--;
list->current_level = top_level;
/* adjust items */
list->items--;
deleted = TRUE;
}
/* free memory */
free(update);
return deleted;
}
/* delete all matching items from list */
int skiplist_delete_all(skiplist *list, void *data) {
int deleted = 0;
int total_deleted = 0;
/* NOTE: there is a more efficient way to do this... */
while((deleted = skiplist_delete_first(list, data)) == 1)
total_deleted++;
return total_deleted;
}
/* delete specific node from list */
int skiplist_delete_node(skiplist *list, void *node_ptr) {
void *data = NULL;
skiplistnode **update = NULL;
skiplistnode *thenode = NULL;
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
int level = 0;
int top_level = 0;
int deleted = FALSE;
int x = 0;
if(list == NULL || node_ptr == NULL)
return ERROR;
/* we'll need the data from the node to first find the node */
thenode = (skiplistnode *)node_ptr;
data = thenode->data;
/* initialize update vector */
if((update = (skiplistnode **)malloc(sizeof(skiplistnode *) * list->max_levels)) == NULL)
return ERROR;
for(x = 0; x < list->max_levels; x++)
update[x] = NULL;
/* find location in list */
thisnode = list->head;
for(top_level = level = list->current_level; level >= 0; level--) {
while((nextnode = thisnode->forward[level])) {
/* next node would be too far */
if(list->compare_function(nextnode->data, data) > 0)
break;
/* this is the exact node we want */
if(list->compare_function(nextnode->data, data) == 0 && nextnode == thenode)
break;
thisnode = nextnode;
}
update[level] = thisnode;
}
/* we found a match! (value + pointers match) */
if(nextnode && list->compare_function(nextnode->data, data) == 0 && nextnode == thenode) {
/* adjust level pointers to bypass (soon to be) removed node */
for(level = 0; level <= top_level; level++) {
thisnode = update[level];
if(thisnode->forward[level] != nextnode)
break;
thisnode->forward[level] = nextnode->forward[level];
}
/* free node memory */
free(nextnode);
/* adjust top/current level of list is necessary */
while(list->head->forward[top_level] == NULL && top_level > 0)
top_level--;
list->current_level = top_level;
/* adjust items */
list->items--;
deleted = TRUE;
}
/* free memory */
free(update);
return deleted;
}
nagios/common/snprintf.c 0000664 0000000 0000000 00000104350 12210155146 0015635 0 ustar 00root root 0000000 0000000 /*
* NOTE: If you change this file, please merge it into rsync, samba, etc.
*/
/*
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell (papowell@astart.com)
* It may be used for any purpose as long as this notice remains intact
* on all source code distributions
*/
/**************************************************************
* Original:
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
* A bombproof version of doprnt (dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that
* the version here does not include floating point...
*
* snprintf() is used instead of sprintf() as it does limit checks
* for string length. This covers a nasty loophole.
*
* The other functions are there to prevent NULL pointers from
* causing nast effects.
*
* More Recently:
* Brandon Long 9/15/96 for mutt 0.43
* This was ugly. It is still ugly. I opted out of floating point
* numbers, but the formatter understands just about everything
* from the normal C string format, at least as far as I can tell from
* the Solaris 2.5 printf(3S) man page.
*
* Brandon Long 10/22/97 for mutt 0.87.1
* Ok, added some minimal floating point support, which means this
* probably requires libm on most operating systems. Don't yet
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
* was pretty badly broken, it just wasn't being exercised in ways
* which showed it, so that's been fixed. Also, formated the code
* to mutt conventions, and removed dead code left over from the
* original. Also, there is now a builtin-test, just compile with:
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
* and run snprintf for results.
*
* Thomas Roessler 01/27/98 for mutt 0.89i
* The PGP code was using unsigned hexadecimal formats.
* Unfortunately, unsigned formats simply didn't work.
*
* Michael Elkins 03/05/98 for mutt 0.90.8
* The original code assumed that both snprintf() and vsnprintf() were
* missing. Some systems only have snprintf() but not vsnprintf(), so
* the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
*
* Andrew Tridgell (tridge@samba.org) Oct 1998
* fixed handling of %.0f
* added test for HAVE_LONG_DOUBLE
*
* tridge@samba.org, idra@samba.org, April 2001
* got rid of fcvt code (twas buggy and made testing harder)
* added C99 semantics
*
* date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0
* actually print args for %g and %e
*
* date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0
* Since includes.h isn't included here, VA_COPY has to be defined here. I don't
* see any include file that is guaranteed to be here, so I'm defining it
* locally. Fixes AIX and Solaris builds.
*
* date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13
* put the ifdef for HAVE_VA_COPY in one place rather than in lots of
* functions
*
* date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4
* Fix usage of va_list passed as an arg. Use __va_copy before using it
* when it exists.
*
* date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14
* 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.
*
* Martin Pool (mbp@samba.org) April 2003
* Remove NO_CONFIG_H so that the test case can be built within a source
* tree with less trouble.
* Remove unnecessary SAFE_FREE() definition.
*
* Martin Pool (mbp@samba.org) May 2003
* Put in a prototype for dummy_snprintf() to quiet compiler warnings.
*
* Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
* if the C library has some snprintf functions already.
*
* Darren Tucker (dtucker@zip.com.au) 2005
* Fix bug allowing read overruns of the source string with "%.*s"
* Usually harmless unless the read runs outside the process' allocation
* (eg if your malloc does guard pages) in which case it will segfault.
* From OpenSSH. Also added test for same.
*
* Simo Sorce (idra@samba.org) Jan 2006
*
* Add support for position independent parameters
* fix fmtstr now it conforms to sprintf wrt min.max
*
**************************************************************/
#ifndef NO_CONFIG_H
/* 02/28/2006 EG changed path to config.h to match Nagios distro */
#include "../include/config.h"
#else
#define NULL 0
#endif
#ifdef TEST_SNPRINTF /* need math library headers for testing */
/* In test mode, we pretend that this system doesn't have any snprintf
* functions, regardless of what config.h says. */
# undef HAVE_SNPRINTF
# undef HAVE_VSNPRINTF
# undef HAVE_C99_VSNPRINTF
# undef HAVE_ASPRINTF
# undef HAVE_VASPRINTF
# include
#endif /* TEST_SNPRINTF */
#ifdef HAVE_STRING_H
#include
#endif
#ifdef HAVE_STRINGS_H
#include
#endif
#ifdef HAVE_CTYPE_H
#include
#endif
#include
#include
#ifdef HAVE_STDLIB_H
#include
#endif
#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF)
/* only include stdio.h if we are not re-defining snprintf or vsnprintf */
#include
/* make the compiler happy with an empty file */
void dummy_snprintf(void);
void dummy_snprintf(void) {}
#endif /* HAVE_SNPRINTF, etc */
#ifdef HAVE_LONG_DOUBLE
#define LDOUBLE long double
#else
#define LDOUBLE double
#endif
#ifdef HAVE_LONG_LONG
#define LLONG long long
#else
#define LLONG long
#endif
#ifndef VA_COPY
#ifdef HAVE_VA_COPY
#define VA_COPY(dest, src) va_copy(dest, src)
#else
#ifdef HAVE___VA_COPY
#define VA_COPY(dest, src) __va_copy(dest, src)
#else
#define VA_COPY(dest, src) (dest) = (src)
#endif
#endif
/*
* dopr(): poor man's version of doprintf
*/
/* format read states */
#define DP_S_DEFAULT 0
#define DP_S_FLAGS 1
#define DP_S_MIN 2
#define DP_S_DOT 3
#define DP_S_MAX 4
#define DP_S_MOD 5
#define DP_S_CONV 6
#define DP_S_DONE 7
/* format flags - Bits */
#define DP_F_MINUS (1 << 0)
#define DP_F_PLUS (1 << 1)
#define DP_F_SPACE (1 << 2)
#define DP_F_NUM (1 << 3)
#define DP_F_ZERO (1 << 4)
#define DP_F_UP (1 << 5)
#define DP_F_UNSIGNED (1 << 6)
/* Conversion Flags */
#define DP_C_CHAR 1
#define DP_C_SHORT 2
#define DP_C_LONG 3
#define DP_C_LDOUBLE 4
#define DP_C_LLONG 5
/* Chunk types */
#define CNK_FMT_STR 0
#define CNK_INT 1
#define CNK_OCTAL 2
#define CNK_UINT 3
#define CNK_HEX 4
#define CNK_FLOAT 5
#define CNK_CHAR 6
#define CNK_STRING 7
#define CNK_PTR 8
#define CNK_NUM 9
#define CNK_PRCNT 10
#define char_to_int(p) ((p)- '0')
#ifndef MAX
#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
#endif
/* yes this really must be a ||. Don't muck with this (tridge) */
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
struct pr_chunk {
int type; /* chunk type */
int num; /* parameter number */
int min;
int max;
int flags;
int cflags;
int start;
int len;
LLONG value;
LDOUBLE fvalue;
char *strvalue;
void *pnum;
struct pr_chunk *min_star;
struct pr_chunk *max_star;
struct pr_chunk *next;
};
struct pr_chunk_x {
struct pr_chunk **chunks;
int num;
};
static size_t dopr(char *buffer, size_t maxlen, const char *format,
va_list args_in);
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags);
static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
static struct pr_chunk *new_chunk(void);
static int add_cnk_list_entry(struct pr_chunk_x **list,
int max_num, struct pr_chunk *chunk);
static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) {
char ch;
int state;
int pflag;
int pnum;
int pfirst;
size_t currlen;
va_list args;
const char *base;
struct pr_chunk *chunks = NULL;
struct pr_chunk *cnk = NULL;
struct pr_chunk_x *clist = NULL;
int max_pos;
size_t ret = -1;
VA_COPY(args, args_in);
state = DP_S_DEFAULT;
pfirst = 1;
pflag = 0;
pnum = 0;
max_pos = 0;
base = format;
ch = *format++;
/* retrieve the string structure as chunks */
while(state != DP_S_DONE) {
if(ch == '\0')
state = DP_S_DONE;
switch(state) {
case DP_S_DEFAULT:
if(cnk) {
cnk->next = new_chunk();
cnk = cnk->next;
}
else {
cnk = new_chunk();
}
if(!cnk) goto done;
if(!chunks) chunks = cnk;
if(ch == '%') {
state = DP_S_FLAGS;
ch = *format++;
}
else {
cnk->type = CNK_FMT_STR;
cnk->start = format - base - 1;
while((ch != '\0') && (ch != '%')) ch = *format++;
cnk->len = format - base - cnk->start - 1;
}
break;
case DP_S_FLAGS:
switch(ch) {
case '-':
cnk->flags |= DP_F_MINUS;
ch = *format++;
break;
case '+':
cnk->flags |= DP_F_PLUS;
ch = *format++;
break;
case ' ':
cnk->flags |= DP_F_SPACE;
ch = *format++;
break;
case '#':
cnk->flags |= DP_F_NUM;
ch = *format++;
break;
case '0':
cnk->flags |= DP_F_ZERO;
ch = *format++;
break;
case 'I':
/* internationalization not supported yet */
ch = *format++;
break;
default:
state = DP_S_MIN;
break;
}
break;
case DP_S_MIN:
if(isdigit((unsigned char)ch)) {
cnk->min = 10 * cnk->min + char_to_int(ch);
ch = *format++;
}
else if(ch == '$') {
if(!pfirst && !pflag) {
/* parameters must be all positioned or none */
goto done;
}
if(pfirst) {
pfirst = 0;
pflag = 1;
}
if(cnk->min == 0) /* what ?? */
goto done;
cnk->num = cnk->min;
cnk->min = 0;
ch = *format++;
}
else if(ch == '*') {
if(pfirst) pfirst = 0;
cnk->min_star = new_chunk();
if(!cnk->min_star) /* out of memory :-( */
goto done;
cnk->min_star->type = CNK_INT;
if(pflag) {
int num;
ch = *format++;
if(!isdigit((unsigned char)ch)) {
/* parameters must be all positioned or none */
goto done;
}
for(num = 0; isdigit((unsigned char)ch); ch = *format++) {
num = 10 * num + char_to_int(ch);
}
cnk->min_star->num = num;
if(ch != '$') /* what ?? */
goto done;
}
else {
cnk->min_star->num = ++pnum;
}
max_pos = add_cnk_list_entry(&clist, max_pos, cnk->min_star);
if(max_pos == 0) /* out of memory :-( */
goto done;
ch = *format++;
state = DP_S_DOT;
}
else {
if(pfirst) pfirst = 0;
state = DP_S_DOT;
}
break;
case DP_S_DOT:
if(ch == '.') {
state = DP_S_MAX;
ch = *format++;
}
else {
state = DP_S_MOD;
}
break;
case DP_S_MAX:
if(isdigit((unsigned char)ch)) {
if(cnk->max < 0)
cnk->max = 0;
cnk->max = 10 * cnk->max + char_to_int(ch);
ch = *format++;
}
else if(ch == '$') {
if(!pfirst && !pflag) {
/* parameters must be all positioned or none */
goto done;
}
if(cnk->max <= 0) /* what ?? */
goto done;
cnk->num = cnk->max;
cnk->max = -1;
ch = *format++;
}
else if(ch == '*') {
cnk->max_star = new_chunk();
if(!cnk->max_star) /* out of memory :-( */
goto done;
cnk->max_star->type = CNK_INT;
if(pflag) {
int num;
ch = *format++;
if(!isdigit((unsigned char)ch)) {
/* parameters must be all positioned or none */
goto done;
}
for(num = 0; isdigit((unsigned char)ch); ch = *format++) {
num = 10 * num + char_to_int(ch);
}
cnk->max_star->num = num;
if(ch != '$') /* what ?? */
goto done;
}
else {
cnk->max_star->num = ++pnum;
}
max_pos = add_cnk_list_entry(&clist, max_pos, cnk->max_star);
if(max_pos == 0) /* out of memory :-( */
goto done;
ch = *format++;
state = DP_S_MOD;
}
else {
state = DP_S_MOD;
}
break;
case DP_S_MOD:
switch(ch) {
case 'h':
cnk->cflags = DP_C_SHORT;
ch = *format++;
if(ch == 'h') {
cnk->cflags = DP_C_CHAR;
ch = *format++;
}
break;
case 'l':
cnk->cflags = DP_C_LONG;
ch = *format++;
if(ch == 'l') { /* It's a long long */
cnk->cflags = DP_C_LLONG;
ch = *format++;
}
break;
case 'L':
cnk->cflags = DP_C_LDOUBLE;
ch = *format++;
break;
default:
break;
}
state = DP_S_CONV;
break;
case DP_S_CONV:
if(cnk->num == 0) cnk->num = ++pnum;
max_pos = add_cnk_list_entry(&clist, max_pos, cnk);
if(max_pos == 0) /* out of memory :-( */
goto done;
switch(ch) {
case 'd':
case 'i':
cnk->type = CNK_INT;
break;
case 'o':
cnk->type = CNK_OCTAL;
cnk->flags |= DP_F_UNSIGNED;
break;
case 'u':
cnk->type = CNK_UINT;
cnk->flags |= DP_F_UNSIGNED;
break;
case 'X':
cnk->flags |= DP_F_UP;
case 'x':
cnk->type = CNK_HEX;
cnk->flags |= DP_F_UNSIGNED;
break;
case 'A':
/* hex float not supported yet */
case 'E':
case 'G':
case 'F':
cnk->flags |= DP_F_UP;
case 'a':
/* hex float not supported yet */
case 'e':
case 'f':
case 'g':
cnk->type = CNK_FLOAT;
break;
case 'c':
cnk->type = CNK_CHAR;
break;
case 's':
cnk->type = CNK_STRING;
break;
case 'p':
cnk->type = CNK_PTR;
break;
case 'n':
cnk->type = CNK_NUM;
break;
case '%':
cnk->type = CNK_PRCNT;
break;
default:
/* Unknown, bail out*/
goto done;
}
ch = *format++;
state = DP_S_DEFAULT;
break;
case DP_S_DONE:
break;
default:
/* hmm? */
break; /* some picky compilers need this */
}
}
/* retieve the format arguments */
for(pnum = 0; pnum < max_pos; pnum++) {
int i;
if(clist[pnum].num == 0) {
/* ignoring a parameter should not be permitted
* all parameters must be matched at least once
* BUT seem some system ignore this rule ...
* at least my glibc based system does --SSS
*/
#ifdef DEBUG_SNPRINTF
printf("parameter at position %d not used\n", pnum + 1);
#endif
/* eat the parameter */
va_arg(args, int);
continue;
}
for(i = 1; i < clist[pnum].num; i++) {
if(clist[pnum].chunks[0]->type != clist[pnum].chunks[i]->type) {
/* nooo noo no!
* all the references to a parameter
* must be of the same type
*/
goto done;
}
}
cnk = clist[pnum].chunks[0];
switch(cnk->type) {
case CNK_INT:
if(cnk->cflags == DP_C_SHORT)
cnk->value = va_arg(args, int);
else if(cnk->cflags == DP_C_LONG)
cnk->value = va_arg(args, long int);
else if(cnk->cflags == DP_C_LLONG)
cnk->value = va_arg(args, LLONG);
else
cnk->value = va_arg(args, int);
for(i = 1; i < clist[pnum].num; i++) {
clist[pnum].chunks[i]->value = cnk->value;
}
break;
case CNK_OCTAL:
case CNK_UINT:
case CNK_HEX:
if(cnk->cflags == DP_C_SHORT)
cnk->value = va_arg(args, unsigned int);
else if(cnk->cflags == DP_C_LONG)
cnk->value = (long)va_arg(args, unsigned long int);
else if(cnk->cflags == DP_C_LLONG)
cnk->value = (LLONG)va_arg(args, unsigned LLONG);
else
cnk->value = (long)va_arg(args, unsigned int);
for(i = 1; i < clist[pnum].num; i++) {
clist[pnum].chunks[i]->value = cnk->value;
}
break;
case CNK_FLOAT:
if(cnk->cflags == DP_C_LDOUBLE)
cnk->fvalue = va_arg(args, LDOUBLE);
else
cnk->fvalue = va_arg(args, double);
for(i = 1; i < clist[pnum].num; i++) {
clist[pnum].chunks[i]->fvalue = cnk->fvalue;
}
break;
case CNK_CHAR:
cnk->value = va_arg(args, int);
for(i = 1; i < clist[pnum].num; i++) {
clist[pnum].chunks[i]->value = cnk->value;
}
break;
case CNK_STRING:
cnk->strvalue = va_arg(args, char *);
if(!cnk->strvalue) cnk->strvalue = "(NULL)";
for(i = 1; i < clist[pnum].num; i++) {
clist[pnum].chunks[i]->strvalue = cnk->strvalue;
}
break;
case CNK_PTR:
cnk->strvalue = va_arg(args, void *);
for(i = 1; i < clist[pnum].num; i++) {
clist[pnum].chunks[i]->strvalue = cnk->strvalue;
}
break;
case CNK_NUM:
if(cnk->cflags == DP_C_CHAR)
cnk->pnum = va_arg(args, char *);
else if(cnk->cflags == DP_C_SHORT)
cnk->pnum = va_arg(args, short int *);
else if(cnk->cflags == DP_C_LONG)
cnk->pnum = va_arg(args, long int *);
else if(cnk->cflags == DP_C_LLONG)
cnk->pnum = va_arg(args, LLONG *);
else
cnk->pnum = va_arg(args, int *);
for(i = 1; i < clist[pnum].num; i++) {
clist[pnum].chunks[i]->pnum = cnk->pnum;
}
break;
case CNK_PRCNT:
break;
default:
/* what ?? */
goto done;
}
}
/* print out the actual string from chunks */
currlen = 0;
cnk = chunks;
while(cnk) {
int len, min, max;
if(cnk->min_star) min = cnk->min_star->value;
else min = cnk->min;
if(cnk->max_star) max = cnk->max_star->value;
else max = cnk->max;
switch(cnk->type) {
case CNK_FMT_STR:
if(maxlen != 0 && maxlen > currlen) {
if(maxlen > (currlen + cnk->len)) len = cnk->len;
else len = maxlen - currlen;
memcpy(&(buffer[currlen]), &(base[cnk->start]), len);
}
currlen += cnk->len;
break;
case CNK_INT:
case CNK_UINT:
fmtint(buffer, &currlen, maxlen, cnk->value, 10, min, max, cnk->flags);
break;
case CNK_OCTAL:
fmtint(buffer, &currlen, maxlen, cnk->value, 8, min, max, cnk->flags);
break;
case CNK_HEX:
fmtint(buffer, &currlen, maxlen, cnk->value, 16, min, max, cnk->flags);
break;
case CNK_FLOAT:
fmtfp(buffer, &currlen, maxlen, cnk->fvalue, min, max, cnk->flags);
break;
case CNK_CHAR:
dopr_outch(buffer, &currlen, maxlen, cnk->value);
break;
case CNK_STRING:
if(max == -1) {
max = strlen(cnk->strvalue);
}
fmtstr(buffer, &currlen, maxlen, cnk->strvalue, cnk->flags, min, max);
break;
case CNK_PTR:
fmtint(buffer, &currlen, maxlen, (long)(cnk->strvalue), 16, min, max, cnk->flags);
break;
case CNK_NUM:
if(cnk->cflags == DP_C_CHAR)
*((char *)(cnk->pnum)) = (char)currlen;
else if(cnk->cflags == DP_C_SHORT)
*((short int *)(cnk->pnum)) = (short int)currlen;
else if(cnk->cflags == DP_C_LONG)
*((long int *)(cnk->pnum)) = (long int)currlen;
else if(cnk->cflags == DP_C_LLONG)
*((LLONG *)(cnk->pnum)) = (LLONG)currlen;
else
*((int *)(cnk->pnum)) = (int)currlen;
break;
case CNK_PRCNT:
dopr_outch(buffer, &currlen, maxlen, '%');
break;
default:
/* what ?? */
goto done;
}
cnk = cnk->next;
}
if(maxlen != 0) {
if(currlen < maxlen - 1)
buffer[currlen] = '\0';
else if(maxlen > 0)
buffer[maxlen - 1] = '\0';
}
ret = currlen;
done:
while(chunks) {
cnk = chunks->next;
free(chunks);
chunks = cnk;
}
if(clist) {
for(pnum = 0; pnum < max_pos; pnum++) {
if(clist[pnum].chunks) free(clist[pnum].chunks);
}
free(clist);
}
return ret;
}
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max) {
int padlen, strln; /* amount to pad */
int cnt = 0;
#ifdef DEBUG_SNPRINTF
printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
#endif
if(value == 0) {
value = "";
}
for(strln = 0; strln < max && value[strln]; ++strln); /* strlen */
padlen = min - strln;
if(padlen < 0)
padlen = 0;
if(flags & DP_F_MINUS)
padlen = -padlen; /* Left Justify */
while(padlen > 0) {
dopr_outch(buffer, currlen, maxlen, ' ');
--padlen;
}
while(*value && (cnt < max)) {
dopr_outch(buffer, currlen, maxlen, *value++);
++cnt;
}
while(padlen < 0) {
dopr_outch(buffer, currlen, maxlen, ' ');
++padlen;
}
}
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags) {
int signvalue = 0;
unsigned long uvalue;
char convert[20];
int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
int caps = 0;
if(max < 0)
max = 0;
uvalue = value;
if(!(flags & DP_F_UNSIGNED)) {
if(value < 0) {
signvalue = '-';
uvalue = -value;
}
else {
if(flags & DP_F_PLUS) /* Do a sign (+/i) */
signvalue = '+';
else if(flags & DP_F_SPACE)
signvalue = ' ';
}
}
if(flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
do {
convert[place++] =
(caps ? "0123456789ABCDEF" : "0123456789abcdef")
[uvalue % (unsigned)base ];
uvalue = (uvalue / (unsigned)base);
}
while(uvalue && (place < 20));
if(place == 20) place--;
convert[place] = 0;
zpadlen = max - place;
spadlen = min - MAX(max, place) - (signvalue ? 1 : 0);
if(zpadlen < 0) zpadlen = 0;
if(spadlen < 0) spadlen = 0;
if(flags & DP_F_ZERO) {
zpadlen = MAX(zpadlen, spadlen);
spadlen = 0;
}
if(flags & DP_F_MINUS)
spadlen = -spadlen; /* Left Justifty */
#ifdef DEBUG_SNPRINTF
printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
zpadlen, spadlen, min, max, place);
#endif
/* Spaces */
while(spadlen > 0) {
dopr_outch(buffer, currlen, maxlen, ' ');
--spadlen;
}
/* Sign */
if(signvalue)
dopr_outch(buffer, currlen, maxlen, signvalue);
/* Zeros */
if(zpadlen > 0) {
while(zpadlen > 0) {
dopr_outch(buffer, currlen, maxlen, '0');
--zpadlen;
}
}
/* Digits */
while(place > 0)
dopr_outch(buffer, currlen, maxlen, convert[--place]);
/* Left Justified spaces */
while(spadlen < 0) {
dopr_outch(buffer, currlen, maxlen, ' ');
++spadlen;
}
}
static LDOUBLE abs_val(LDOUBLE value) {
LDOUBLE result = value;
if(value < 0)
result = -value;
return result;
}
static LDOUBLE POW10(int exp) {
LDOUBLE result = 1;
while(exp) {
result *= 10;
exp--;
}
return result;
}
static LLONG ROUND(LDOUBLE value) {
LLONG intpart;
intpart = (LLONG)value;
value = value - intpart;
if(value >= 0.5) intpart++;
return intpart;
}
/* a replacement for modf that doesn't need the math library. Should
be portable, but slow */
static double my_modf(double x0, double *iptr) {
int i;
long l;
double x = x0;
double f = 1.0;
for(i = 0; i < 100; i++) {
l = (long)x;
if(l <= (x + 1) && l >= (x - 1)) break;
x *= 0.1;
f *= 10.0;
}
if(i == 100) {
/* yikes! the number is beyond what we can handle. What do we do? */
(*iptr) = 0;
return 0;
}
if(i != 0) {
double i2;
double ret;
ret = my_modf(x0 - l * f, &i2);
(*iptr) = l * f + i2;
return ret;
}
(*iptr) = l;
return x - (*iptr);
}
static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags) {
int signvalue = 0;
double ufvalue;
char iconvert[311];
char fconvert[311];
int iplace = 0;
int fplace = 0;
int padlen = 0; /* amount to pad */
int zpadlen = 0;
int caps = 0;
int idx;
double intpart;
double fracpart;
double temp;
/*
* AIX manpage says the default is 0, but Solaris says the default
* is 6, and sprintf on AIX defaults to 6
*/
if(max < 0)
max = 6;
ufvalue = abs_val(fvalue);
if(fvalue < 0) {
signvalue = '-';
}
else {
if(flags & DP_F_PLUS) { /* Do a sign (+/i) */
signvalue = '+';
}
else {
if(flags & DP_F_SPACE)
signvalue = ' ';
}
}
#if 0
if(flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
#endif
#if 0
if(max == 0) ufvalue += 0.5; /* if max = 0 we must round */
#endif
/*
* Sorry, we only support 9 digits past the decimal because of our
* conversion method
*/
if(max > 9)
max = 9;
/* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of 10
*/
temp = ufvalue;
my_modf(temp, &intpart);
fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
if(fracpart >= POW10(max)) {
intpart++;
fracpart -= POW10(max);
}
/* Convert integer part */
do {
temp = intpart * 0.1;
my_modf(temp, &intpart);
idx = (int)((temp - intpart + 0.05) * 10.0);
/* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
/* printf ("%llf, %f, %x\n", temp, intpart, idx); */
iconvert[iplace++] =
(caps ? "0123456789ABCDEF" : "0123456789abcdef")[idx];
}
while(intpart && (iplace < 311));
if(iplace == 311) iplace--;
iconvert[iplace] = 0;
/* Convert fractional part */
if(fracpart) {
do {
temp = fracpart * 0.1;
my_modf(temp, &fracpart);
idx = (int)((temp - fracpart + 0.05) * 10.0);
/* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
/* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
fconvert[fplace++] =
(caps ? "0123456789ABCDEF" : "0123456789abcdef")[idx];
}
while(fracpart && (fplace < 311));
if(fplace == 311) fplace--;
}
fconvert[fplace] = 0;
/* -1 for decimal point, another -1 if we are printing a sign */
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
zpadlen = max - fplace;
if(zpadlen < 0) zpadlen = 0;
if(padlen < 0)
padlen = 0;
if(flags & DP_F_MINUS)
padlen = -padlen; /* Left Justifty */
if((flags & DP_F_ZERO) && (padlen > 0)) {
if(signvalue) {
dopr_outch(buffer, currlen, maxlen, signvalue);
--padlen;
signvalue = 0;
}
while(padlen > 0) {
dopr_outch(buffer, currlen, maxlen, '0');
--padlen;
}
}
while(padlen > 0) {
dopr_outch(buffer, currlen, maxlen, ' ');
--padlen;
}
if(signvalue)
dopr_outch(buffer, currlen, maxlen, signvalue);
while(iplace > 0)
dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]);
#ifdef DEBUG_SNPRINTF
printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
#endif
/*
* Decimal point. This should probably use locale to find the correct
* char to print out.
*/
if(max > 0) {
dopr_outch(buffer, currlen, maxlen, '.');
while(zpadlen > 0) {
dopr_outch(buffer, currlen, maxlen, '0');
--zpadlen;
}
while(fplace > 0)
dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]);
}
while(padlen < 0) {
dopr_outch(buffer, currlen, maxlen, ' ');
++padlen;
}
}
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) {
if(*currlen < maxlen) {
buffer[(*currlen)] = c;
}
(*currlen)++;
}
static struct pr_chunk *new_chunk(void) {
struct pr_chunk *new_c = (struct pr_chunk *)malloc(sizeof(struct pr_chunk));
if(!new_c)
return NULL;
new_c->type = 0;
new_c->num = 0;
new_c->min = 0;
new_c->min_star = NULL;
new_c->max = -1;
new_c->max_star = NULL;
new_c->flags = 0;
new_c->cflags = 0;
new_c->start = 0;
new_c->len = 0;
new_c->value = 0;
new_c->fvalue = 0;
new_c->strvalue = NULL;
new_c->pnum = NULL;
new_c->next = NULL;
return new_c;
}
static int add_cnk_list_entry(struct pr_chunk_x **list,
int max_num, struct pr_chunk *chunk) {
struct pr_chunk_x *l;
struct pr_chunk **c;
int max;
int cnum;
int i, pos;
if(chunk->num > max_num) {
max = chunk->num;
if(*list == NULL) {
l = (struct pr_chunk_x *)malloc(sizeof(struct pr_chunk_x) * max);
pos = 0;
}
else {
l = (struct pr_chunk_x *)realloc(*list, sizeof(struct pr_chunk_x) * max);
pos = max_num;
}
if(l == NULL) {
for(i = 0; i < max; i++) {
if((*list)[i].chunks) free((*list)[i].chunks);
}
return 0;
}
for(i = pos; i < max; i++) {
l[i].chunks = NULL;
l[i].num = 0;
}
}
else {
l = *list;
max = max_num;
}
i = chunk->num - 1;
cnum = l[i].num + 1;
if(l[i].chunks == NULL) {
c = (struct pr_chunk **)malloc(sizeof(struct pr_chunk *) * cnum);
}
else {
c = (struct pr_chunk **)realloc(l[i].chunks, sizeof(struct pr_chunk *) * cnum);
}
if(c == NULL) {
for(i = 0; i < max; i++) {
if(l[i].chunks) free(l[i].chunks);
}
return 0;
}
c[l[i].num] = chunk;
l[i].chunks = c;
l[i].num = cnum;
*list = l;
return max;
}
int smb_vsnprintf(char *str, size_t count, const char *fmt, va_list args) {
return dopr(str, count, fmt, args);
}
#define vsnprintf smb_vsnprintf
#endif
/* yes this really must be a ||. Don't muck with this (tridge)
*
* The logic for these two is that we need our own definition if the
* OS *either* has no definition of *sprintf, or if it does have one
* that doesn't work properly according to the autoconf test.
*/
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
int smb_snprintf(char *str, size_t count, const char *fmt, ...) {
size_t ret;
va_list ap;
va_start(ap, fmt);
ret = vsnprintf(str, count, fmt, ap);
va_end(ap);
return ret;
}
#define snprintf smb_snprintf
#endif
#endif
#ifndef HAVE_VASPRINTF
int vasprintf(char **ptr, const char *format, va_list ap) {
int ret;
va_list ap2;
VA_COPY(ap2, ap);
ret = vsnprintf(NULL, 0, format, ap2);
if(ret <= 0) return ret;
(*ptr) = (char *)malloc(ret + 1);
if(!*ptr) return -1;
VA_COPY(ap2, ap);
ret = vsnprintf(*ptr, ret + 1, format, ap2);
return ret;
}
#endif
#ifndef HAVE_ASPRINTF
int asprintf(char **ptr, const char *format, ...) {
va_list ap;
int ret;
*ptr = NULL;
va_start(ap, format);
ret = vasprintf(ptr, format, ap);
va_end(ap);
return ret;
}
#endif
#ifdef TEST_SNPRINTF
int sprintf(char *str, const char *fmt, ...);
int main(void) {
char buf1[1024];
char buf2[1024];
char *buf3;
char *fp_fmt[] = {
"%1.1f",
"%-1.5f",
"%1.5f",
"%123.9f",
"%10.5f",
"% 10.5f",
"%+22.9f",
"%+4.9f",
"%01.3f",
"%4f",
"%3.1f",
"%3.2f",
"%.0f",
"%f",
"%-8.8f",
"%-9.9f",
NULL
};
double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996,
0.9996, 1.996, 4.136, 5.030201, 0.00205,
/* END LIST */ 0
};
char *int_fmt[] = {
"%-1.5d",
"%1.5d",
"%123.9d",
"%5.5d",
"%10.5d",
"% 10.5d",
"%+22.33d",
"%01.3d",
"%4d",
"%d",
NULL
};
long int_nums[] = { -1, 134, 91340, 341, 0203, 0, 1234567890};
char *str_fmt[] = {
"%10.5s",
"%-10.5s",
"%5.10s",
"%-5.10s",
"%10.1s",
"%0.10s",
"%10.0s",
"%1.10s",
"%s",
"%.1s",
"%.10s",
"%10s",
NULL
};
char *str_vals[] = {"hello", "a", "", "a longer string", NULL};
int x, y;
int fail = 0;
int num = 0;
int l1, l2;
printf("Testing snprintf format codes against system sprintf...\n");
for(x = 0; fp_fmt[x] ; x++) {
for(y = 0; fp_nums[y] != 0 ; y++) {
buf1[0] = buf2[0] = '\0';
l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]);
l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
sprintf(buf2, fp_fmt[x], fp_nums[y]);
buf1[1023] = buf1[1023] = '\0';
if(strcmp(buf1, buf2) || (l1 != l2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
fp_fmt[x], l1, buf1, l2, buf2);
fail++;
}
num++;
}
}
for(x = 0; int_fmt[x] ; x++) {
for(y = 0; int_nums[y] != 0 ; y++) {
buf1[0] = buf2[0] = '\0';
l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]);
l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
sprintf(buf2, int_fmt[x], int_nums[y]);
buf1[1023] = buf1[1023] = '\0';
if(strcmp(buf1, buf2) || (l1 != l2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
int_fmt[x], l1, buf1, l2, buf2);
fail++;
}
num++;
}
}
for(x = 0; str_fmt[x] ; x++) {
for(y = 0; str_vals[y] != 0 ; y++) {
buf1[0] = buf2[0] = '\0';
l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]);
l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);
sprintf(buf2, str_fmt[x], str_vals[y]);
buf1[1023] = buf1[1023] = '\0';
if(strcmp(buf1, buf2) || (l1 != l2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
str_fmt[x], l1, buf1, l2, buf2);
fail++;
}
num++;
}
}
#define BUFSZ 2048
buf1[0] = buf2[0] = '\0';
if((buf3 = malloc(BUFSZ)) == NULL) {
fail++;
}
else {
num++;
memset(buf3, 'a', BUFSZ);
snprintf(buf1, sizeof(buf1), "%.*s", 1, buf3);
buf1[1023] = '\0';
if(strcmp(buf1, "a") != 0) {
printf("length limit buf1 '%s' expected 'a'\n", buf1);
fail++;
}
}
buf1[0] = buf2[0] = '\0';
l1 = snprintf(buf1, sizeof(buf1), "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9);
l2 = sprintf(buf2, "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9);
buf1[1023] = buf1[1023] = '\0';
if(strcmp(buf1, buf2) || (l1 != l2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
"%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2);
fail++;
}
buf1[0] = buf2[0] = '\0';
l1 = snprintf(buf1, sizeof(buf1), "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9);
l2 = sprintf(buf2, "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9);
buf1[1023] = buf1[1023] = '\0';
if(strcmp(buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
"%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2);
fail++;
}
#if 0
buf1[0] = buf2[0] = '\0';
l1 = snprintf(buf1, sizeof(buf1), "%lld", (LLONG)1234567890);
l2 = sprintf(buf2, "%lld", (LLONG)1234567890);
buf1[1023] = buf1[1023] = '\0';
if(strcmp(buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
"%lld", l1, buf1, l2, buf2);
fail++;
}
buf1[0] = buf2[0] = '\0';
l1 = snprintf(buf1, sizeof(buf1), "%Lf", (LDOUBLE)890.1234567890123);
l2 = sprintf(buf2, "%Lf", (LDOUBLE)890.1234567890123);
buf1[1023] = buf1[1023] = '\0';
if(strcmp(buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
"%Lf", l1, buf1, l2, buf2);
fail++;
}
#endif
printf("%d tests failed out of %d.\n", fail, num);
printf("seeing how many digits we support\n");
{
double v0 = 0.12345678901234567890123456789012345678901;
for(x = 0; x < 100; x++) {
double p = pow(10, x);
double r = v0 * p;
snprintf(buf1, sizeof(buf1), "%1.1f", r);
sprintf(buf2, "%1.1f", r);
if(strcmp(buf1, buf2)) {
printf("we seem to support %d digits\n", x - 1);
break;
}
}
}
return 0;
}
#endif /* TEST_SNPRINTF */
nagios/common/statusdata.c 0000664 0000000 0000000 00000041071 12210155146 0016147 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* STATUSDATA.C - External status data for Nagios CGIs
*
* Copyright (c) 2000-2006 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 10-19-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.
*
*****************************************************************************/
/*********** COMMON HEADER FILES ***********/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/statusdata.h"
#ifdef NSCORE
#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;
hoststatus *hoststatus_list_tail = NULL;
servicestatus *servicestatus_list = NULL;
servicestatus *servicestatus_list_tail = NULL;
hoststatus **hoststatus_hashlist = NULL;
servicestatus **servicestatus_hashlist = NULL;
extern int use_pending_states;
#endif
#ifdef NSCORE
/******************************************************************/
/****************** TOP-LEVEL OUTPUT FUNCTIONS ********************/
/******************************************************************/
/* 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;
}
/* update all status data (aggregated dump) */
int update_all_status_data(void) {
int result = OK;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
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;
}
/* 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;
}
/* updates program status info */
int update_program_status(int aggregated_dump) {
#ifdef USE_EVENT_BROKER
/* send data to event broker (non-aggregated dumps only) */
if(aggregated_dump == FALSE)
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;
}
/* updates host status info */
int update_host_status(host *hst, int aggregated_dump) {
#ifdef USE_EVENT_BROKER
/* send data to event broker (non-aggregated dumps only) */
if(aggregated_dump == FALSE)
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;
}
/* updates service status info */
int update_service_status(service *svc, int aggregated_dump) {
#ifdef USE_EVENT_BROKER
/* send data to event broker (non-aggregated dumps only) */
if(aggregated_dump == FALSE)
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;
}
/* updates contact status info */
int update_contact_status(contact *cntct, int aggregated_dump) {
#ifdef USE_EVENT_BROKER
/* send data to event broker (non-aggregated dumps only) */
if(aggregated_dump == FALSE)
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
#ifdef NSCGI
/******************************************************************/
/******************* TOP-LEVEL INPUT FUNCTIONS ********************/
/******************************************************************/
/* 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;
}
/******************************************************************/
/****************** CHAINED HASH FUNCTIONS ************************/
/******************************************************************/
/* adds hoststatus to hash list in memory */
int add_hoststatus_to_hashlist(hoststatus *new_hoststatus) {
hoststatus *temp_hoststatus = NULL;
hoststatus *lastpointer = NULL;
int hashslot = 0;
int i = 0;
/* initialize hash list */
if(hoststatus_hashlist == NULL) {
hoststatus_hashlist = (hoststatus **)malloc(sizeof(hoststatus *) * HOSTSTATUS_HASHSLOTS);
if(hoststatus_hashlist == NULL)
return 0;
for(i = 0; i < HOSTSTATUS_HASHSLOTS; i++)
hoststatus_hashlist[i] = NULL;
}
if(!new_hoststatus)
return 0;
hashslot = hashfunc(new_hoststatus->host_name, NULL, HOSTSTATUS_HASHSLOTS);
lastpointer = NULL;
for(temp_hoststatus = hoststatus_hashlist[hashslot]; temp_hoststatus && compare_hashdata(temp_hoststatus->host_name, NULL, new_hoststatus->host_name, NULL) < 0; temp_hoststatus = temp_hoststatus->nexthash)
lastpointer = temp_hoststatus;
if(!temp_hoststatus || (compare_hashdata(temp_hoststatus->host_name, NULL, new_hoststatus->host_name, NULL) != 0)) {
if(lastpointer)
lastpointer->nexthash = new_hoststatus;
else
hoststatus_hashlist[hashslot] = new_hoststatus;
new_hoststatus->nexthash = temp_hoststatus;
return 1;
}
/* else already exists */
return 0;
}
int add_servicestatus_to_hashlist(servicestatus *new_servicestatus) {
servicestatus *temp_servicestatus = NULL, *lastpointer = NULL;
int hashslot = 0;
int i = 0;
/* initialize hash list */
if(servicestatus_hashlist == NULL) {
servicestatus_hashlist = (servicestatus **)malloc(sizeof(servicestatus *) * SERVICESTATUS_HASHSLOTS);
if(servicestatus_hashlist == NULL)
return 0;
for(i = 0; i < SERVICESTATUS_HASHSLOTS; i++)
servicestatus_hashlist[i] = NULL;
}
if(!new_servicestatus)
return 0;
hashslot = hashfunc(new_servicestatus->host_name, new_servicestatus->description, SERVICESTATUS_HASHSLOTS);
lastpointer = NULL;
for(temp_servicestatus = servicestatus_hashlist[hashslot]; temp_servicestatus && compare_hashdata(temp_servicestatus->host_name, temp_servicestatus->description, new_servicestatus->host_name, new_servicestatus->description) < 0; temp_servicestatus = temp_servicestatus->nexthash)
lastpointer = temp_servicestatus;
if(!temp_servicestatus || (compare_hashdata(temp_servicestatus->host_name, temp_servicestatus->description, new_servicestatus->host_name, new_servicestatus->description) != 0)) {
if(lastpointer)
lastpointer->nexthash = new_servicestatus;
else
servicestatus_hashlist[hashslot] = new_servicestatus;
new_servicestatus->nexthash = temp_servicestatus;
return 1;
}
/* else already exists */
return 0;
}
/******************************************************************/
/********************** ADDITION FUNCTIONS ************************/
/******************************************************************/
/* adds a host status entry to the list in memory */
int add_host_status(hoststatus *new_hoststatus) {
char date_string[MAX_DATETIME_LENGTH];
/* make sure we have what we need */
if(new_hoststatus == NULL)
return ERROR;
if(new_hoststatus->host_name == NULL)
return ERROR;
/* massage host status a bit */
if(new_hoststatus != NULL) {
switch(new_hoststatus->status) {
case 0:
new_hoststatus->status = HOST_UP;
break;
case 1:
new_hoststatus->status = HOST_DOWN;
break;
case 2:
new_hoststatus->status = HOST_UNREACHABLE;
break;
default:
new_hoststatus->status = HOST_UP;
break;
}
if(new_hoststatus->has_been_checked == FALSE) {
if(use_pending_states == TRUE)
new_hoststatus->status = HOST_PENDING;
my_free(new_hoststatus->plugin_output);
if(new_hoststatus->should_be_scheduled == TRUE) {
get_time_string(&new_hoststatus->next_check, date_string, sizeof(date_string), LONG_DATE_TIME);
asprintf(&new_hoststatus->plugin_output, "Host check scheduled for %s", date_string);
}
else {
/* passive-only hosts that have just been scheduled for a forced check */
if(new_hoststatus->checks_enabled == FALSE && new_hoststatus->next_check != (time_t)0L && (new_hoststatus->check_options & CHECK_OPTION_FORCE_EXECUTION)) {
get_time_string(&new_hoststatus->next_check, date_string, sizeof(date_string), LONG_DATE_TIME);
asprintf(&new_hoststatus->plugin_output, "Forced host check scheduled for %s", date_string);
}
/* passive-only hosts not scheduled to be checked */
else
new_hoststatus->plugin_output = (char *)strdup("Host is not scheduled to be checked...");
}
}
}
new_hoststatus->next = NULL;
new_hoststatus->nexthash = NULL;
/* add new hoststatus to hoststatus chained hash list */
if(!add_hoststatus_to_hashlist(new_hoststatus))
return ERROR;
/* object cache file is already sorted, so just add new items to end of list */
if(hoststatus_list == NULL) {
hoststatus_list = new_hoststatus;
hoststatus_list_tail = new_hoststatus;
}
else {
hoststatus_list_tail->next = new_hoststatus;
hoststatus_list_tail = new_hoststatus;
}
return OK;
}
/* adds a service status entry to the list in memory */
int add_service_status(servicestatus *new_svcstatus) {
char date_string[MAX_DATETIME_LENGTH];
/* make sure we have what we need */
if(new_svcstatus == NULL)
return ERROR;
if(new_svcstatus->host_name == NULL || new_svcstatus->description == NULL)
return ERROR;
/* massage service status a bit */
if(new_svcstatus != NULL) {
switch(new_svcstatus->status) {
case 0:
new_svcstatus->status = SERVICE_OK;
break;
case 1:
new_svcstatus->status = SERVICE_WARNING;
break;
case 2:
new_svcstatus->status = SERVICE_CRITICAL;
break;
case 3:
new_svcstatus->status = SERVICE_UNKNOWN;
break;
default:
new_svcstatus->status = SERVICE_OK;
break;
}
if(new_svcstatus->has_been_checked == FALSE) {
if(use_pending_states == TRUE)
new_svcstatus->status = SERVICE_PENDING;
my_free(new_svcstatus->plugin_output);
if(new_svcstatus->should_be_scheduled == TRUE) {
get_time_string(&new_svcstatus->next_check, date_string, sizeof(date_string), LONG_DATE_TIME);
asprintf(&new_svcstatus->plugin_output, "Service check scheduled for %s", date_string);
}
else {
/* passive-only services that have just been scheduled for a forced check */
if(new_svcstatus->checks_enabled == FALSE && new_svcstatus->next_check != (time_t)0L && (new_svcstatus->check_options & CHECK_OPTION_FORCE_EXECUTION)) {
get_time_string(&new_svcstatus->next_check, date_string, sizeof(date_string), LONG_DATE_TIME);
asprintf(&new_svcstatus->plugin_output, "Forced service check scheduled for %s", date_string);
}
/* passive-only services not scheduled to be checked */
else
new_svcstatus->plugin_output = (char *)strdup("Service is not scheduled to be checked...");
}
}
}
new_svcstatus->next = NULL;
new_svcstatus->nexthash = NULL;
/* add new servicestatus to servicestatus chained hash list */
if(!add_servicestatus_to_hashlist(new_svcstatus))
return ERROR;
/* object cache file is already sorted, so just add new items to end of list */
if(servicestatus_list == NULL) {
servicestatus_list = new_svcstatus;
servicestatus_list_tail = new_svcstatus;
}
else {
servicestatus_list_tail->next = new_svcstatus;
servicestatus_list_tail = new_svcstatus;
}
return OK;
}
/******************************************************************/
/*********************** CLEANUP FUNCTIONS ************************/
/******************************************************************/
/* free all memory for status data */
void free_status_data(void) {
hoststatus *this_hoststatus = NULL;
hoststatus *next_hoststatus = NULL;
servicestatus *this_svcstatus = NULL;
servicestatus *next_svcstatus = NULL;
/* free memory for the host status list */
for(this_hoststatus = hoststatus_list; this_hoststatus != NULL; this_hoststatus = next_hoststatus) {
next_hoststatus = this_hoststatus->next;
my_free(this_hoststatus->host_name);
my_free(this_hoststatus->plugin_output);
my_free(this_hoststatus->long_plugin_output);
my_free(this_hoststatus->perf_data);
my_free(this_hoststatus);
}
/* free memory for the service status list */
for(this_svcstatus = servicestatus_list; this_svcstatus != NULL; this_svcstatus = next_svcstatus) {
next_svcstatus = this_svcstatus->next;
my_free(this_svcstatus->host_name);
my_free(this_svcstatus->description);
my_free(this_svcstatus->plugin_output);
my_free(this_svcstatus->long_plugin_output);
my_free(this_svcstatus->perf_data);
my_free(this_svcstatus);
}
/* free hash lists reset list pointers */
my_free(hoststatus_hashlist);
my_free(servicestatus_hashlist);
hoststatus_list = NULL;
servicestatus_list = NULL;
return;
}
/******************************************************************/
/************************ SEARCH FUNCTIONS ************************/
/******************************************************************/
/* find a host status entry */
hoststatus *find_hoststatus(char *host_name) {
hoststatus *temp_hoststatus = NULL;
if(host_name == NULL || hoststatus_hashlist == NULL)
return NULL;
for(temp_hoststatus = hoststatus_hashlist[hashfunc(host_name, NULL, HOSTSTATUS_HASHSLOTS)]; temp_hoststatus && compare_hashdata(temp_hoststatus->host_name, NULL, host_name, NULL) < 0; temp_hoststatus = temp_hoststatus->nexthash);
if(temp_hoststatus && (compare_hashdata(temp_hoststatus->host_name, NULL, host_name, NULL) == 0))
return temp_hoststatus;
return NULL;
}
/* find a service status entry */
servicestatus *find_servicestatus(char *host_name, char *svc_desc) {
servicestatus *temp_servicestatus = NULL;
if(host_name == NULL || svc_desc == NULL || servicestatus_hashlist == NULL)
return NULL;
for(temp_servicestatus = servicestatus_hashlist[hashfunc(host_name, svc_desc, SERVICESTATUS_HASHSLOTS)]; temp_servicestatus && compare_hashdata(temp_servicestatus->host_name, temp_servicestatus->description, host_name, svc_desc) < 0; temp_servicestatus = temp_servicestatus->nexthash);
if(temp_servicestatus && (compare_hashdata(temp_servicestatus->host_name, temp_servicestatus->description, host_name, svc_desc) == 0))
return temp_servicestatus;
return NULL;
}
/******************************************************************/
/*********************** UTILITY FUNCTIONS ************************/
/******************************************************************/
/* gets the total number of services of a certain state for a specific host */
int get_servicestatus_count(char *host_name, int type) {
servicestatus *temp_status = NULL;
int count = 0;
if(host_name == NULL)
return 0;
for(temp_status = servicestatus_list; temp_status != NULL; temp_status = temp_status->next) {
if(temp_status->status & type) {
if(!strcmp(host_name, temp_status->host_name))
count++;
}
}
return count;
}
#endif
nagios/config.guess 0000775 0000000 0000000 00000126703 12210155146 0014664 0 ustar 00root root 0000000 0000000 #! /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.
timestamp='2006-12-08'
# 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
# (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.
#
# 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.
#
# 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.
#
# 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.
#
# The plan is that this can be called by configure scripts if you
# don't specify an explicit build system type.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION]
Output the configuration name of the system \`$me' is run on.
Operation modes:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to ."
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.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
* )
break ;;
esac
done
if test $# != 0; then
echo "$me: too many arguments$help" >&2
exit 1
fi
trap 'exit 1' 1 2 15
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.
# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
# use `HOST_CC' if defined, but it is deprecated.
# Portable tmp directory creation inspired by the Autoconf team.
set_cc_for_build='
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
: ${TMPDIR=/tmp} ;
{ tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
case $CC_FOR_BUILD,$HOST_CC,$CC in
,,) echo "int x;" > $dummy.c ;
for c in cc gcc c89 c99 ; do
if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
CC_FOR_BUILD="$c"; break ;
fi ;
done ;
if test x"$CC_FOR_BUILD" = x ; then
CC_FOR_BUILD=no_compiler_found ;
fi
;;
,,*) CC_FOR_BUILD=$CC ;;
,*,*) CC_FOR_BUILD=$HOST_CC ;;
esac ; set_cc_for_build= ;'
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
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
# 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*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
# compatibility and a consistent mechanism for selecting the
# object file format.
#
# 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)`
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 ;;
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently, or will in the future.
case "${UNAME_MACHINE_ARCH}" in
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
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
os=netbsd
else
os=netbsdelf
fi
;;
*)
os=netbsd
;;
esac
# The OS release
# Debian GNU/NetBSD machines have a different userland, and
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
case "${UNAME_VERSION}" in
Debian*)
release='-gnu'
;;
*)
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
;;
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}"
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
exit ;;
*:ekkoBSD:*:*)
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
exit ;;
*:SolidBSD:*:*)
echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
exit ;;
macppc:MirBSD:*:*)
echo powerpc-unknown-mirbsd${UNAME_RELEASE}
exit ;;
*:MirBSD:*:*)
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
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}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
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" ;;
"EV4.5 (21064)")
UNAME_MACHINE="alpha" ;;
"LCA4 (21066/21068)")
UNAME_MACHINE="alpha" ;;
"EV5 (21164)")
UNAME_MACHINE="alphaev5" ;;
"EV5.6 (21164A)")
UNAME_MACHINE="alphaev56" ;;
"EV5.6 (21164PC)")
UNAME_MACHINE="alphapca56" ;;
"EV5.7 (21164PC)")
UNAME_MACHINE="alphapca57" ;;
"EV6 (21264)")
UNAME_MACHINE="alphaev6" ;;
"EV6.7 (21264A)")
UNAME_MACHINE="alphaev67" ;;
"EV6.8CB (21264C)")
UNAME_MACHINE="alphaev68" ;;
"EV6.8AL (21264B)")
UNAME_MACHINE="alphaev68" ;;
"EV6.8CX (21264D)")
UNAME_MACHINE="alphaev68" ;;
"EV6.9A (21264/EV69A)")
UNAME_MACHINE="alphaev69" ;;
"EV7 (21364)")
UNAME_MACHINE="alphaev7" ;;
"EV7.9 (21364A)")
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 ;;
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
# of the specific Alpha model?
echo alpha-pc-interix
exit ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
exit ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-unknown-sysv4
exit ;;
*:[Aa]miga[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-amigaos
exit ;;
*:[Mm]orph[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-morphos
exit ;;
*:OS/390:*:*)
echo i370-ibm-openedition
exit ;;
*:z/VM:*:*)
echo s390-ibm-zvmoe
exit ;;
*: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:*:*)
echo arm-unknown-riscos
exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
echo hppa1.1-hitachi-hiuxmpp
exit ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit ;;
NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
exit ;;
DRS?6000:unix:4.0:6*)
echo sparc-icl-nx6
exit ;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7; exit ;;
esac ;;
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/[^.]*//'`
exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
exit ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
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
case "`/bin/arch`" in
sun3)
echo m68k-sun-sunos${UNAME_RELEASE}
;;
sun4)
echo sparc-sun-sunos${UNAME_RELEASE}
;;
esac
exit ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
exit ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
# > m68000). The system name ranges from "MiNT" over "FreeMiNT"
# to the lowercase version "mint" (or "freemint"). Finally
# the system name "TOS" denotes a system which is actually not
# 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}
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
echo m68k-milan-mint${UNAME_RELEASE}
exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
echo m68k-hades-mint${UNAME_RELEASE}
exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
echo m68k-unknown-mint${UNAME_RELEASE}
exit ;;
m68k:machten:*:*)
echo m68k-apple-machten${UNAME_RELEASE}
exit ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
exit ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
echo clipper-intergraph-clix${UNAME_RELEASE}
exit ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#ifdef __cplusplus
#include /* for printf() prototype */
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c &&
dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
SYSTEM_NAME=`$dummy $dummyarg` &&
{ echo "$SYSTEM_NAME"; exit; }
echo mips-mips-riscos${UNAME_RELEASE}
exit ;;
Motorola:PowerMAX_OS:*:*)
echo powerpc-motorola-powermax
exit ;;
Motorola:*:4.3:PL8-*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
exit ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
exit ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
exit ;;
AViiON:dgux:*:*)
# 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 ] || \
[ ${TARGET_BINARY_INTERFACE}x = x ]
then
echo m88k-dg-dgux${UNAME_RELEASE}
else
echo m88k-dg-dguxbcs${UNAME_RELEASE}
fi
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
exit ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
exit ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
exit ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
echo i386-ibm-aix
exit ;;
ia64:AIX:*:*)
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
exit ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
then
echo "$SYSTEM_NAME"
else
echo rs6000-ibm-aix3.2.5
fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
exit ;;
*:AIX:*:[45])
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`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
exit ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
exit ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit ;;
9000/[34678]??:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
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
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#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);
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`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
if [ ${HP_ARCH} = "hppa2.0w" ]
then
eval $set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
# generating 64-bit code. GNU and HP use different nomenclature:
#
# $ CC_FOR_BUILD=cc ./config.guess
# => hppa2.0w-hp-hpux11.23
# $ 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
then
HP_ARCH="hppa2.0w"
else
HP_ARCH="hppa64"
fi
fi
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit ;;
ia64:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ia64-hp-hpux${HPUX_REV}
exit ;;
3050*:HI-UX:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
{ echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2
exit ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
exit ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit ;;
i*86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
echo ${UNAME_MACHINE}-unknown-osf1mk
else
echo ${UNAME_MACHINE}-unknown-osf1
fi
exit ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*T3E:*:*:*)
echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*SV1:*:*:*)
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
*:UNICOS/mp:*:*)
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 ;;
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}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit ;;
sparc*:BSD/OS:*:*)
echo sparc-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:FreeBSD:*:*)
case ${UNAME_MACHINE} in
pc98)
echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
amd64)
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
*)
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
esac
exit ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit ;;
i*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
i*:windows32*:*)
# 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 ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-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
# UNAME_MACHINE based on the output of uname instead of i386?
echo i586-pc-interix
exit ;;
i*:UWIN*:*)
echo ${UNAME_MACHINE}-pc-uwin
exit ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
echo x86_64-unknown-cygwin
exit ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin
exit ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
*:GNU:*:*)
# the GNU system
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`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
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
arm*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
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
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
PCA57) UNAME_MACHINE=alphapca56 ;;
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}
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 ;;
esac
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-gnu
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
exit ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-gnu
exit ;;
x86_64:Linux:*:*)
echo x86_64-unknown-linux-gnu
exit ;;
xtensa:Linux:*:*)
echo xtensa-unknown-linux-gnu
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
# sysname and nodename.
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,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
echo ${UNAME_MACHINE}-pc-os2-emx
exit ;;
i*86:XTS-300:*:STOP)
echo ${UNAME_MACHINE}-unknown-stop
exit ;;
i*86:atheos:*:*)
echo ${UNAME_MACHINE}-unknown-atheos
exit ;;
i*86:syllable:*:*)
echo ${UNAME_MACHINE}-pc-syllable
exit ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit ;;
i*86:*DOS:*:*)
echo ${UNAME_MACHINE}-pc-msdosdjgpp
exit ;;
i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
else
echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
fi
exit ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
exit ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
else
echo ${UNAME_MACHINE}-pc-sysv32
fi
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 ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit ;;
paragon:*:*:*)
echo i860-intel-osf1
exit ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
exit ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
exit ;;
mc68k:UNIX:SYSTEM5:3.51m)
echo m68k-convergent-sysv
exit ;;
M680?0:D-NIX:5.3:*)
echo m68k-diab-dnix
exit ;;
M68*:*:R3V[5678]*:*)
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
OS_REL=''
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; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
exit ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit ;;
TSUNAMI:LynxOS:2.*:*)
echo sparc-unknown-lynxos${UNAME_RELEASE}
exit ;;
rs6000:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
echo powerpc-unknown-lynxos${UNAME_RELEASE}
exit ;;
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv${UNAME_RELEASE}
exit ;;
RM*:ReliantUNIX-*:*:*)
echo mips-sni-sysv4
exit ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
echo ${UNAME_MACHINE}-sni-sysv4
else
echo ns32k-sni-sysv
fi
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
echo hppa1.1-stratus-sysv4
exit ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
exit ;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
echo ${UNAME_MACHINE}-stratus-vos
exit ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
exit ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit ;;
news*:NEWS-OS:6*:*)
echo mips-sony-newsos6
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
echo powerpc-apple-beos
exit ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
SX-5:SUPER-UX:*:*)
echo sx5-nec-superux${UNAME_RELEASE}
exit ;;
SX-6:SUPER-UX:*:*)
echo sx6-nec-superux${UNAME_RELEASE}
exit ;;
SX-7:SUPER-UX:*:*)
echo sx7-nec-superux${UNAME_RELEASE}
exit ;;
SX-8:SUPER-UX:*:*)
echo sx8-nec-superux${UNAME_RELEASE}
exit ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
exit ;;
*:Rhapsody:*:*)
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
case $UNAME_PROCESSOR in
unknown) UNAME_PROCESSOR=powerpc ;;
esac
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = "x86"; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
exit ;;
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
NSE-?:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
NSR-?:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
exit ;;
BS2000:POSIX*:*:*)
echo bs2000-siemens-sysv
exit ;;
DS/*:UNIX_System_V:*:*)
echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
exit ;;
*:Plan9:*:*)
# "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
UNAME_MACHINE=i386
else
UNAME_MACHINE="$cputype"
fi
echo ${UNAME_MACHINE}-unknown-plan9
exit ;;
*:TOPS-10:*:*)
echo pdp10-unknown-tops10
exit ;;
*:TENEX:*:*)
echo pdp10-unknown-tenex
exit ;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
echo pdp10-dec-tops20
exit ;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
echo pdp10-xkl-tops20
exit ;;
*:TOPS-20:*:*)
echo pdp10-unknown-tops20
exit ;;
*:ITS:*:*)
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
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`
case "${UNAME_MACHINE}" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
V*) echo vax-dec-vms ; exit ;;
esac ;;
*:XENIX:*:SysV)
echo i386-pc-xenix
exit ;;
i*86:skyos:*:*)
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
exit ;;
i*86:rdos:*:*)
echo ${UNAME_MACHINE}-pc-rdos
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.
config.guess timestamp = $timestamp
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
hostinfo = `(hostinfo) 2>/dev/null`
/bin/universe = `(/bin/universe) 2>/dev/null`
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
/bin/arch = `(/bin/arch) 2>/dev/null`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
UNAME_MACHINE = ${UNAME_MACHINE}
UNAME_RELEASE = ${UNAME_RELEASE}
UNAME_SYSTEM = ${UNAME_SYSTEM}
UNAME_VERSION = ${UNAME_VERSION}
EOF
exit 1
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
nagios/config.sub 0000775 0000000 0000000 00000077553 12210155146 0014337 0 ustar 00root root 0000000 0000000 #! /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.
timestamp='2006-12-08'
# 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
# (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.
#
# 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.
#
# 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.
# Please send patches to . Submit a context
# diff and a properly formatted ChangeLog entry.
#
# 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.
# 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.
# Each package is responsible for reporting which valid configurations
# it does not support. The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS
$0 [OPTION] ALIAS
Canonicalize a configuration name.
Operation modes:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
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.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help"
exit 1 ;;
*local*)
# First pass through any local machine types.
echo $1
exit ;;
* )
break ;;
esac
done
case $# in
0) echo "$me: missing argument$help" >&2
exit 1;;
1) ;;
*) echo "$me: too many arguments$help" >&2
exit 1;;
esac
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# 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* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
then os=`echo $1 | sed 's/.*-/-/'`
else os=; fi
;;
esac
### Let's recognize common machines as not being operating systems so
### that things like config.sub decstation-3100 work. We also
### recognize some manufacturers as not being operating systems, so we
### can provide default operating systems below.
case $os in
-sun*os*)
# Prevent following clause from handling this invalid input.
;;
-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-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)
os=
basic_machine=$1
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
;;
-scout)
;;
-wrs)
os=-vxworks
basic_machine=$1
;;
-chorusos*)
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
-hiux*)
os=-hiuxwe2
;;
-sco6)
os=-sco5v6
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco4)
os=-sco3.2v4
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2.[4-9]*)
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2v[4-9]*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-udk*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-isc)
os=-isc2.2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-clix*)
basic_machine=clipper-intergraph
;;
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*)
os=-lynxos
;;
-ptx*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
;;
-windowsnt*)
os=`echo $os | sed -e 's/windowsnt/winnt/'`
;;
-psos*)
os=-psos
;;
-mint | -mint[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
esac
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
| 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 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| mips64vr | mips64vrel \
| mips64orion | mips64orionel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| mt \
| msp430 \
| nios | nios2 \
| ns16k | ns32k \
| or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| score \
| sh | sh[1234] | sh[24]a | 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 \
| spu | strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| we32k \
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
| z8k)
basic_machine=$basic_machine-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12)
# Motorola 68HC11/12.
basic_machine=$basic_machine-unknown
os=-none
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
ms1)
basic_machine=mt-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.
i*86 | x86_64)
basic_machine=$basic_machine-pc
;;
# Object if more than one company name word.
*-*-*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| mips64vr-* | mips64vrel-* \
| mips64orion-* | mips64orionel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nios-* | nios2-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[24]a-* | 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-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
| xstormy16-* | xtensa-* \
| ymp-* \
| z8k-*)
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
386bsd)
basic_machine=i386-unknown
os=-bsd
;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
basic_machine=m68000-att
;;
3b*)
basic_machine=we32k-att
;;
a29khif)
basic_machine=a29k-amd
os=-udi
;;
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
;;
alliant | fx80)
basic_machine=fx80-alliant
;;
altos | altos3068)
basic_machine=m68k-altos
;;
am29k)
basic_machine=a29k-none
os=-bsd
;;
amd64)
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
;;
amiga | amiga-*)
basic_machine=m68k-unknown
;;
amigaos | amigados)
basic_machine=m68k-unknown
os=-amigaos
;;
amigaunix | amix)
basic_machine=m68k-unknown
os=-sysv4
;;
apollo68)
basic_machine=m68k-apollo
os=-sysv
;;
apollo68bsd)
basic_machine=m68k-apollo
os=-bsd
;;
aux)
basic_machine=m68k-apple
os=-aux
;;
balance)
basic_machine=ns32k-sequent
os=-dynix
;;
c90)
basic_machine=c90-cray
os=-unicos
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
;;
convex-c2)
basic_machine=c2-convex
os=-bsd
;;
convex-c32)
basic_machine=c32-convex
os=-bsd
;;
convex-c34)
basic_machine=c34-convex
os=-bsd
;;
convex-c38)
basic_machine=c38-convex
os=-bsd
;;
cray | j90)
basic_machine=j90-cray
os=-unicos
;;
craynv)
basic_machine=craynv-cray
os=-unicosmp
;;
cr16c)
basic_machine=cr16c-unknown
os=-elf
;;
crds | unos)
basic_machine=m68k-crds
;;
crisv32 | crisv32-* | etraxfs*)
basic_machine=crisv32-axis
;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
crx)
basic_machine=crx-unknown
os=-elf
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
basic_machine=mips-dec
;;
decsystem10* | dec10*)
basic_machine=pdp10-dec
os=-tops10
;;
decsystem20* | dec20*)
basic_machine=pdp10-dec
os=-tops20
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
basic_machine=m68k-motorola
;;
delta88)
basic_machine=m88k-motorola
os=-sysv3
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
;;
dpx2* | dpx2*-bull)
basic_machine=m68k-bull
os=-sysv3
;;
ebmon29k)
basic_machine=a29k-amd
os=-ebmon
;;
elxsi)
basic_machine=elxsi-elxsi
os=-bsd
;;
encore | umax | mmax)
basic_machine=ns32k-encore
;;
es1800 | OSE68k | ose68k | ose | OSE)
basic_machine=m68k-ericsson
os=-ose
;;
fx2800)
basic_machine=i860-alliant
;;
genix)
basic_machine=ns32k-ns
;;
gmicro)
basic_machine=tron-gmicro
os=-sysv
;;
go32)
basic_machine=i386-pc
os=-go32
;;
h3050r* | hiux*)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
h8300hms)
basic_machine=h8300-hitachi
os=-hms
;;
h8300xray)
basic_machine=h8300-hitachi
os=-xray
;;
h8500hms)
basic_machine=h8500-hitachi
os=-hms
;;
harris)
basic_machine=m88k-harris
os=-sysv3
;;
hp300-*)
basic_machine=m68k-hp
;;
hp300bsd)
basic_machine=m68k-hp
os=-bsd
;;
hp300hpux)
basic_machine=m68k-hp
os=-hpux
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
basic_machine=m68000-hp
;;
hp9k3[2-9][0-9])
basic_machine=m68k-hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
basic_machine=hppa1.1-hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hppa-next)
os=-nextstep3
;;
hppaosf)
basic_machine=hppa1.1-hp
os=-osf
;;
hppro)
basic_machine=hppa1.1-hp
os=-proelf
;;
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
;;
i*86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
i*86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
i*86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
i386mach)
basic_machine=i386-mach
os=-mach
;;
i386-vsta | vsta)
basic_machine=i386-unknown
os=-vsta
;;
iris | iris4d)
basic_machine=mips-sgi
case $os in
-irix*)
;;
*)
os=-irix4
;;
esac
;;
isi68 | isi)
basic_machine=m68k-isi
os=-sysv
;;
m88k-omron*)
basic_machine=m88k-omron
;;
magnum | m3230)
basic_machine=mips-mips
os=-sysv
;;
merlin)
basic_machine=ns32k-utek
os=-sysv
;;
mingw32)
basic_machine=i386-pc
os=-mingw32
;;
miniframe)
basic_machine=m68000-convergent
;;
*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
mips3*-*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
;;
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
;;
morphos)
basic_machine=powerpc-unknown
os=-morphos
;;
msdos)
basic_machine=i386-pc
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
;;
netbsd386)
basic_machine=i386-unknown
os=-netbsd
;;
netwinder)
basic_machine=armv4l-rebel
os=-linux
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
os=-newsos
;;
news1000)
basic_machine=m68030-sony
os=-newsos
;;
news-3600 | risc-news)
basic_machine=mips-sony
os=-newsos
;;
necv70)
basic_machine=v70-nec
os=-sysv
;;
next | m*-next )
basic_machine=m68k-next
case $os in
-nextstep* )
;;
-ns2*)
os=-nextstep2
;;
*)
os=-nextstep3
;;
esac
;;
nh3000)
basic_machine=m68k-harris
os=-cxux
;;
nh[45]000)
basic_machine=m88k-harris
os=-cxux
;;
nindy960)
basic_machine=i960-intel
os=-nindy
;;
mon960)
basic_machine=i960-intel
os=-mon960
;;
nonstopux)
basic_machine=mips-compaq
os=-nonstopux
;;
np1)
basic_machine=np1-gould
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
os=-proelf
;;
openrisc | openrisc-*)
basic_machine=or32-unknown
;;
os400)
basic_machine=powerpc-ibm
os=-os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
os=-ose
;;
os68k)
basic_machine=m68k-none
os=-os68k
;;
pa-hitachi)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
paragon)
basic_machine=i860-intel
os=-osf
;;
pbd)
basic_machine=sparc-tti
;;
pbb)
basic_machine=m68k-tti
;;
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pc98)
basic_machine=i386-pc
;;
pc98-*)
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
;;
pentiumpro | p6 | 6x86 | athlon | athlon_*)
basic_machine=i686-pc
;;
pentiumii | pentium2 | pentiumiii | pentium3)
basic_machine=i686-pc
;;
pentium4)
basic_machine=i786-pc
;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium4-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
;;
power) basic_machine=power-ibm
;;
ppc) basic_machine=powerpc-unknown
;;
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
;;
ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64) basic_machine=powerpc64-unknown
;;
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
basic_machine=powerpc64le-unknown
;;
ppc64le-* | powerpc64little-*)
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ps2)
basic_machine=i386-ibm
;;
pw32)
basic_machine=i586-unknown
os=-pw32
;;
rdos)
basic_machine=i386-pc
os=-rdos
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
;;
rm[46]00)
basic_machine=mips-siemens
;;
rtpc | rtpc-*)
basic_machine=romp-ibm
;;
s390 | s390-*)
basic_machine=s390-ibm
;;
s390x | s390x-*)
basic_machine=s390x-ibm
;;
sa29200)
basic_machine=a29k-amd
os=-udi
;;
sb1)
basic_machine=mipsisa64sb1-unknown
;;
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
sde)
basic_machine=mipsisa32-sde
os=-elf
;;
sei)
basic_machine=mips-sei
os=-seiux
;;
sequent)
basic_machine=i386-sequent
;;
sh)
basic_machine=sh-hitachi
os=-hms
;;
sh5el)
basic_machine=sh5le-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
sparclite-wrs | simso-wrs)
basic_machine=sparclite-wrs
os=-vxworks
;;
sps7)
basic_machine=m68k-bull
os=-sysv2
;;
spur)
basic_machine=spur-unknown
;;
st2000)
basic_machine=m68k-tandem
;;
stratus)
basic_machine=i860-stratus
os=-sysv4
;;
sun2)
basic_machine=m68000-sun
;;
sun2os3)
basic_machine=m68000-sun
os=-sunos3
;;
sun2os4)
basic_machine=m68000-sun
os=-sunos4
;;
sun3os3)
basic_machine=m68k-sun
os=-sunos3
;;
sun3os4)
basic_machine=m68k-sun
os=-sunos4
;;
sun4os3)
basic_machine=sparc-sun
os=-sunos3
;;
sun4os4)
basic_machine=sparc-sun
os=-sunos4
;;
sun4sol2)
basic_machine=sparc-sun
os=-solaris2
;;
sun3 | sun3-*)
basic_machine=m68k-sun
;;
sun4)
basic_machine=sparc-sun
;;
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
;;
sv1)
basic_machine=sv1-cray
os=-unicos
;;
symmetry)
basic_machine=i386-sequent
os=-dynix
;;
t3e)
basic_machine=alphaev5-cray
os=-unicos
;;
t90)
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
;;
tx39)
basic_machine=mipstx39-unknown
;;
tx39el)
basic_machine=mipstx39el-unknown
;;
toad1)
basic_machine=pdp10-xkl
os=-tops20
;;
tower | tower-32)
basic_machine=m68k-ncr
;;
tpf)
basic_machine=s390x-ibm
os=-tpf
;;
udi29k)
basic_machine=a29k-amd
os=-udi
;;
ultra3)
basic_machine=a29k-nyu
os=-sym1
;;
v810 | necv810)
basic_machine=v810-nec
os=-none
;;
vaxv)
basic_machine=vax-dec
os=-sysv
;;
vms)
basic_machine=vax-dec
os=-vms
;;
vpp*|vx|vx-*)
basic_machine=f301-fujitsu
;;
vxworks960)
basic_machine=i960-wrs
os=-vxworks
;;
vxworks68)
basic_machine=m68k-wrs
os=-vxworks
;;
vxworks29k)
basic_machine=a29k-wrs
os=-vxworks
;;
w65*)
basic_machine=w65-wdc
os=-none
;;
w89k-*)
basic_machine=hppa1.1-winbond
os=-proelf
;;
xbox)
basic_machine=i686-pc
os=-mingw32
;;
xps | xps100)
basic_machine=xps100-honeywell
;;
ymp)
basic_machine=ymp-cray
os=-unicos
;;
z8k-*-coff)
basic_machine=z8k-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
;;
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
w89k)
basic_machine=hppa1.1-winbond
;;
op50n)
basic_machine=hppa1.1-oki
;;
op60c)
basic_machine=hppa1.1-oki
;;
romp)
basic_machine=romp-ibm
;;
mmix)
basic_machine=mmix-knuth
;;
rs6000)
basic_machine=rs6000-ibm
;;
vax)
basic_machine=vax-dec
;;
pdp10)
# there are many clones, so DEC is not a safe bet
basic_machine=pdp10-unknown
;;
pdp11)
basic_machine=pdp11-dec
;;
we32k)
basic_machine=we32k-att
;;
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
basic_machine=cydra-cydrome
;;
orion)
basic_machine=orion-highlevel
;;
orion105)
basic_machine=clipper-highlevel
;;
mac | mpw | mac-mpw)
basic_machine=m68k-apple
;;
pmac | pmac-mpw)
basic_machine=powerpc-apple
;;
*-unknown)
# Make sure to match an already-canonicalized machine name.
;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
esac
# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
*-digital*)
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
;;
*-commodore*)
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
;;
*)
;;
esac
# Decode manufacturer-specific aliases for certain operating systems.
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
-solaris)
os=-solaris2
;;
-svr4*)
os=-sysv4
;;
-unixware*)
os=-sysv4.2uw
;;
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# First accept the basic system types.
# The portable systems comes first.
# 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* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -openbsd* | -solidbsd* \
| -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* \
| -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*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
case $basic_machine in
x86-* | i*86-*)
;;
*)
os=-nto$os
;;
esac
;;
-nto-qnx*)
;;
-nto*)
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
-linux-dietlibc)
os=-linux-dietlibc
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
;;
-sunos6*)
os=`echo $os | sed -e 's|sunos6|solaris3|'`
;;
-opened*)
os=-openedition
;;
-os400*)
os=-os400
;;
-wince*)
os=-wince
;;
-osfrose*)
os=-osfrose
;;
-osf*)
os=-osf
;;
-utek*)
os=-bsd
;;
-dynix*)
os=-bsd
;;
-acis*)
os=-aos
;;
-atheos*)
os=-atheos
;;
-syllable*)
os=-syllable
;;
-386bsd)
os=-bsd
;;
-ctix* | -uts*)
os=-sysv
;;
-nova*)
os=-rtmk-nova
;;
-ns2 )
os=-nextstep2
;;
-nsk*)
os=-nsk
;;
# Preserve the version number of sinix5.
-sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
;;
-sinix*)
os=-sysv4
;;
-tpf*)
os=-tpf
;;
-triton*)
os=-sysv3
;;
-oss*)
os=-sysv3
;;
-svr4)
os=-sysv4
;;
-svr3)
os=-sysv3
;;
-sysvr4)
os=-sysv4
;;
# This must come after -sysvr4.
-sysv*)
;;
-ose*)
os=-ose
;;
-es1800*)
os=-ose
;;
-xenix)
os=-xenix
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
;;
-aros*)
os=-aros
;;
-kaos*)
os=-kaos
;;
-zvmoe)
os=-zvmoe
;;
-none)
;;
*)
# Get rid of the `-' at the beginning of $os.
os=`echo $os | sed 's/[^-]*-//'`
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
exit 1
;;
esac
else
# Here we handle the default operating systems that come with various machines.
# The value should be what the vendor currently ships out the door with their
# machine or put another way, the most popular os provided with the machine.
# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system. Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
case $basic_machine in
score-*)
os=-elf
;;
spu-*)
os=-elf
;;
*-acorn)
os=-riscix1.2
;;
arm*-rebel)
os=-linux
;;
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
;;
pdp11-*)
os=-none
;;
*-dec | vax-*)
os=-ultrix4.2
;;
m68*-apollo)
os=-domain
;;
i386-sun)
os=-sunos4.0.2
;;
m68000-sun)
os=-sunos3
# This also exists in the configure program, but was not the
# default.
# os=-sunos4
;;
m68*-cisco)
os=-aout
;;
mips*-cisco)
os=-elf
;;
mips*-*)
os=-elf
;;
or32-*)
os=-coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
os=-sysv3
;;
sparc-* | *-sun)
os=-sunos4.1.1
;;
*-be)
os=-beos
;;
*-haiku)
os=-haiku
;;
*-ibm)
os=-aix
;;
*-knuth)
os=-mmixware
;;
*-wec)
os=-proelf
;;
*-winbond)
os=-proelf
;;
*-oki)
os=-proelf
;;
*-hp)
os=-hpux
;;
*-hitachi)
os=-hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
os=-sysv
;;
*-cbm)
os=-amigaos
;;
*-dg)
os=-dgux
;;
*-dolphin)
os=-sysv3
;;
m68k-ccur)
os=-rtu
;;
m88k-omron*)
os=-luna
;;
*-next )
os=-nextstep
;;
*-sequent)
os=-ptx
;;
*-crds)
os=-unos
;;
*-ns)
os=-genix
;;
i370-*)
os=-mvs
;;
*-next)
os=-nextstep3
;;
*-gould)
os=-sysv
;;
*-highlevel)
os=-bsd
;;
*-encore)
os=-bsd
;;
*-sgi)
os=-irix
;;
*-siemens)
os=-sysv4
;;
*-masscomp)
os=-rtu
;;
f30[01]-fujitsu | f700-fujitsu)
os=-uxpv
;;
*-rom68k)
os=-coff
;;
*-*bug)
os=-coff
;;
*-apple)
os=-macos
;;
*-atari*)
os=-mint
;;
*)
os=-none
;;
esac
fi
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
vendor=unknown
case $basic_machine in
*-unknown)
case $os in
-riscix*)
vendor=acorn
;;
-sunos*)
vendor=sun
;;
-aix*)
vendor=ibm
;;
-beos*)
vendor=be
;;
-hpux*)
vendor=hp
;;
-mpeix*)
vendor=hp
;;
-hiux*)
vendor=hitachi
;;
-unos*)
vendor=crds
;;
-dgux*)
vendor=dg
;;
-luna*)
vendor=omron
;;
-genix*)
vendor=ns
;;
-mvs* | -opened*)
vendor=ibm
;;
-os400*)
vendor=ibm
;;
-ptx*)
vendor=sequent
;;
-tpf*)
vendor=ibm
;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
-aux*)
vendor=apple
;;
-hms*)
vendor=hitachi
;;
-mpw* | -macos*)
vendor=apple
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
vendor=atari
;;
-vos*)
vendor=stratus
;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
echo $basic_machine$os
exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
nagios/configure 0000775 0000000 0000000 00000754053 12210155146 0014260 0 ustar 00root root 0000000 0000000 #! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59.
#
# 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. ##
## --------------------- ##
# Be Bourne compatible
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
# 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
else
as_unset=false
fi
# Work around bugs in pre-3.0 UWIN ksh.
$as_unset ENV MAIL MAILPATH
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
# Required to use basename.
if expr a : '\(a\)' >/dev/null 2>&1; then
as_expr=expr
else
as_expr=false
fi
if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
# Name of the executable.
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'`
# PATH needs CR, and LINENO needs CR and PATH.
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
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 |
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: 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= ;;
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
as_ln_s='ln -s'
fi
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -p'
fi
rm -f conf$$ conf$$.exe conf$$.file
if mkdir -p . 2>/dev/null; then
as_mkdir_p=:
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
as_executable_p="test -f"
# 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'"
# Sed expression to map a string onto a valid variable name.
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
# Name of the host.
# hostname on some systems (SVR3.2, 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_config_libobj_dir=.
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=
PACKAGE_TARNAME=
PACKAGE_VERSION=
PACKAGE_STRING=
PACKAGE_BUGREPORT=
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
# include
#endif
#if HAVE_SYS_STAT_H
# include
#endif
#if STDC_HEADERS
# include
# include
#else
# if HAVE_STDLIB_H
# include
# endif
#endif
#if HAVE_STRING_H
# if !STDC_HEADERS && HAVE_MEMORY_H
# include
# endif
# include
#endif
#if HAVE_STRINGS_H
# include
#endif
#if HAVE_INTTYPES_H
# include
#else
# if HAVE_STDINT_H
# include
# endif
#endif
#if 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'
ac_subst_files=''
# Initialize some variables set by options.
ac_init_help=
ac_init_version=false
# The variables have the same names as the options, with
# dashes changed to underlines.
cache_file=/dev/null
exec_prefix=NONE
no_create=
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
verbose=
x_includes=NONE
x_libraries=NONE
# Installation directory options.
# These are left unexpanded so users can "make install exec_prefix=/foo"
# 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.
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datadir='${prefix}/share'
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'
ac_prev=
for ac_option
do
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval "$ac_prev=\$ac_option"
ac_prev=
continue
fi
ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
# Accept the important Cygnus configure options, so we can diagnose typos.
case $ac_option in
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
bindir=$ac_optarg ;;
-build | --build | --buil | --bui | --bu)
ac_prev=build_alias ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
build_alias=$ac_optarg ;;
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
cache_file=$ac_optarg ;;
--config-cache | -C)
cache_file=config.cache ;;
-datadir | --datadir | --datadi | --datad | --data | --dat | --da)
ac_prev=datadir ;;
-datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
| --da=*)
datadir=$ac_optarg ;;
-disable-* | --disable-*)
ac_feature=`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" ;;
-enable-* | --enable-*)
ac_feature=`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 ;;
esac
eval "enable_$ac_feature='$ac_optarg'" ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
| --exec | --exe | --ex)
ac_prev=exec_prefix ;;
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
exec_prefix=$ac_optarg ;;
-gas | --gas | --ga | --g)
# Obsolete; use --with-gas.
with_gas=yes ;;
-help | --help | --hel | --he | -h)
ac_init_help=long ;;
-help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
ac_init_help=recursive ;;
-help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
ac_init_help=short ;;
-host | --host | --hos | --ho)
ac_prev=host_alias ;;
-host=* | --host=* | --hos=* | --ho=*)
host_alias=$ac_optarg ;;
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
| --includ=* | --inclu=* | --incl=* | --inc=*)
includedir=$ac_optarg ;;
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
infodir=$ac_optarg ;;
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
libdir=$ac_optarg ;;
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
| --libexe | --libex | --libe)
ac_prev=libexecdir ;;
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
| --libexe=* | --libex=* | --libe=*)
libexecdir=$ac_optarg ;;
-localstatedir | --localstatedir | --localstatedi | --localstated \
| --localstate | --localstat | --localsta | --localst \
| --locals | --local | --loca | --loc | --lo)
ac_prev=localstatedir ;;
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
| --localstate=* | --localstat=* | --localsta=* | --localst=* \
| --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
localstatedir=$ac_optarg ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
mandir=$ac_optarg ;;
-nfp | --nfp | --nf)
# Obsolete; use --without-fp.
with_fp=no ;;
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
| --no-cr | --no-c | -n)
no_create=yes ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
| --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
no_recursion=yes ;;
-oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
| --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
| --oldin | --oldi | --old | --ol | --o)
ac_prev=oldincludedir ;;
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
oldincludedir=$ac_optarg ;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
prefix=$ac_optarg ;;
-program-prefix | --program-prefix | --program-prefi | --program-pref \
| --program-pre | --program-pr | --program-p)
ac_prev=program_prefix ;;
-program-prefix=* | --program-prefix=* | --program-prefi=* \
| --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
program_prefix=$ac_optarg ;;
-program-suffix | --program-suffix | --program-suffi | --program-suff \
| --program-suf | --program-su | --program-s)
ac_prev=program_suffix ;;
-program-suffix=* | --program-suffix=* | --program-suffi=* \
| --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
program_suffix=$ac_optarg ;;
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
| --program-transform-n | --program-transform- \
| --program-transform | --program-transfor \
| --program-transfo | --program-transf \
| --program-trans | --program-tran \
| --progr-tra | --program-tr | --program-t)
ac_prev=program_transform_name ;;
-program-transform-name=* | --program-transform-name=* \
| --program-transform-nam=* | --program-transform-na=* \
| --program-transform-n=* | --program-transform-=* \
| --program-transform=* | --program-transfor=* \
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
program_transform_name=$ac_optarg ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
sbindir=$ac_optarg ;;
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
| --sharedst | --shareds | --shared | --share | --shar \
| --sha | --sh)
ac_prev=sharedstatedir ;;
-sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
sharedstatedir=$ac_optarg ;;
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
site=$ac_optarg ;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
srcdir=$ac_optarg ;;
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
| --syscon | --sysco | --sysc | --sys | --sy)
ac_prev=sysconfdir ;;
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
sysconfdir=$ac_optarg ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
ac_prev=target_alias ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
target_alias=$ac_optarg ;;
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
-version | --version | --versio | --versi | --vers | -V)
ac_init_version=: ;;
-with-* | --with-*)
ac_package=`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 ;;
esac
eval "with_$ac_package='$ac_optarg'" ;;
-without-* | --without-*)
ac_package=`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" ;;
--x)
# Obsolete; use --with-x.
with_x=yes ;;
-x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
| --x-incl | --x-inc | --x-in | --x-i)
ac_prev=x_includes ;;
-x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
| --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
x_includes=$ac_optarg ;;
-x-libraries | --x-libraries | --x-librarie | --x-librari \
| --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
ac_prev=x_libraries ;;
-x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
| --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; }; }
;;
*=*)
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'"
export $ac_envvar ;;
*)
# FIXME: should be removed in autoconf 3.0.
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}
;;
esac
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; }; }
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; }; };;
esac
done
# Be sure to have absolute paths.
for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
localstatedir libdir includedir oldincludedir infodir mandir
do
eval ac_val=$`echo $ac_var`
case $ac_val in
[\\/$]* | ?:[\\/]* ) ;;
*) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
{ (exit 1); exit 1; }; };;
esac
done
# There might be people who depend on the old broken behavior: `$host'
# used to hold the argument of --host etc.
# FIXME: To remove some day.
build=$build_alias
host=$host_alias
target=$target_alias
# FIXME: To remove some day.
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
fi
ac_tool_prefix=
test -n "$host_alias" && ac_tool_prefix=$host_alias-
test "$silent" = yes && exec 6>/dev/null
# 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'`
srcdir=$ac_confdir
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
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
#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures this package to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE. See below for descriptions of some of the useful variables.
Defaults for the options are specified in brackets.
Configuration:
-h, --help display this help and exit
--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
--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]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
By default, \`make install' will install all the files in
\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
an installation prefix other than \`$ac_default_prefix' using \`--prefix',
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]
_ACEOF
cat <<\_ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
_ACEOF
fi
if test -n "$ac_init_help"; then
cat <<\_ACEOF
Optional Features:
--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-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-nagios-user=
sets user name to run nagios
--with-nagios-group=
sets group name to run nagios
--with-command-user=
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
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
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.
_ACEOF
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
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 $srcdir in
.) # No --srcdir option. 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_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;;
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
else
echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi
cd $ac_popdir
done
fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
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.
_ACEOF
exit 0
fi
exec 5>config.log
cat >&5 <<_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
$ $0 $@
_ACEOF
{
cat <<_ASUNAME
## --------- ##
## Platform. ##
## --------- ##
hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
/bin/uname -X = `(/bin/uname -X) 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`
/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`
_ASUNAME
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
echo "PATH: $as_dir"
done
} >&5
cat >&5 <<_ACEOF
## ----------- ##
## Core tests. ##
## ----------- ##
_ACEOF
# Keep a trace of the command line.
# Strip out --no-create and --no-recursion so they do not pile up.
# Strip out --silent because we don't want to record it for future runs.
# Also quote any args containing shell meta-characters.
# Make two passes to allow for proper duplicate-argument suppression.
ac_configure_args=
ac_configure_args0=
ac_configure_args1=
ac_sep=
ac_must_keep_next=false
for ac_pass in 1 2
do
for ac_arg
do
case $ac_arg in
-no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
2)
ac_configure_args1="$ac_configure_args1 '$ac_arg'"
if test $ac_must_keep_next = true; then
ac_must_keep_next=false # Got value, back to normal.
else
case $ac_arg in
*=* | --config-cache | -C | -disable-* | --disable-* \
| -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
| -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
| -with-* | --with-* | -without-* | --without-* | --x)
case "$ac_configure_args0 " in
"$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
esac
;;
-* ) 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=" "
;;
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; }
# 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.
trap 'exit_status=$?
# Save into config.log some information that might help in debugging.
{
echo
cat <<\_ASBOX
## ---------------- ##
## Cache variables. ##
## ---------------- ##
_ASBOX
echo
# The following way of writing the cache mishandles newlines in values,
{
(set) 2>&1 |
case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
*ac_space=\ *)
sed -n \
"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"
;;
esac;
}
echo
cat <<\_ASBOX
## ----------------- ##
## Output variables. ##
## ----------------- ##
_ASBOX
echo
for ac_var in $ac_subst_vars
do
eval ac_val=$`echo $ac_var`
echo "$ac_var='"'"'$ac_val'"'"'"
done | sort
echo
if test -n "$ac_subst_files"; then
cat <<\_ASBOX
## ------------- ##
## Output files. ##
## ------------- ##
_ASBOX
echo
for ac_var in $ac_subst_files
do
eval ac_val=$`echo $ac_var`
echo "$ac_var='"'"'$ac_val'"'"'"
done | sort
echo
fi
if test -s confdefs.h; then
cat <<\_ASBOX
## ----------- ##
## confdefs.h. ##
## ----------- ##
_ASBOX
echo
sed "/^$/d" confdefs.h | sort
echo
fi
test "$ac_signal" != 0 &&
echo "$as_me: caught signal $ac_signal"
echo "$as_me: exit $exit_status"
} >&5
rm -f core *.core &&
rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
exit $exit_status
' 0
for ac_signal in 1 2 13 15; do
trap 'ac_signal='$ac_signal'; { (exit 1); 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
# Predefined preprocessor variables.
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
# 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
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;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file"
fi
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
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"
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;}
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;}
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=:
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=$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'" ;;
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; }; }
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
ac_config_headers="$ac_config_headers include/config.h include/snprintf.h"
PKG_NAME=nagios
PKG_VERSION="3.5.1"
PKG_HOME_URL="http://www.nagios.org/"
PKG_REL_DATE="08-30-2013"
ac_aux_dir=
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
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/install.sh -c"
break
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; }; }
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.
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AmigaOS /C/install, which installs bootblocks on floppy discs
# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# 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
if test -z "$INSTALL"; then
if test "${ac_cv_path_install+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&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/* | \
/etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
/usr/ucb/* ) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
# Don't use installbsd from OSF since it installs stuff as root
# 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 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.
:
elif test $ac_prog = install &&
grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# 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
fi
fi
done
done
;;
esac
done
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
# break other packages using the cache if that directory is
# removed, or if the path is relative.
INSTALL=$ac_install_sh
fi
fi
echo "$as_me:$LINENO: result: $INSTALL" >&5
echo "${ECHO_T}$INSTALL" >&6
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
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; }; }
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
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; }; }
fi
echo "$as_me:$LINENO: result: $ac_cv_build" >&5
echo "${ECHO_T}$ac_cv_build" >&6
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/'`
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
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; }; }
fi
echo "$as_me:$LINENO: result: $ac_cv_host" >&5
echo "${ECHO_T}$ac_cv_host" >&6
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_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
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
else
if test -n "$CC"; then
ac_cv_prog_CC="$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_CC="${ac_tool_prefix}gcc"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
echo "$as_me:$LINENO: result: $CC" >&5
echo "${ECHO_T}$CC" >&6
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}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
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="gcc"
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
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.
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
else
if test -n "$CC"; then
ac_cv_prog_CC="$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_CC="${ac_tool_prefix}cc"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
echo "$as_me:$LINENO: result: $CC" >&5
echo "${ECHO_T}$CC" >&6
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}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
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
ac_prog_rejected=no
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
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
break 2
fi
done
done
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
set dummy $ac_cv_prog_CC
shift
if test $# != 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
echo "$as_me:$LINENO: result: $CC" >&5
echo "${ECHO_T}$CC" >&6
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
fi
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
for ac_prog in cl
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
else
if test -n "$CC"; then
ac_cv_prog_CC="$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_CC="$ac_tool_prefix$ac_prog"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
echo "$as_me:$LINENO: result: $CC" >&5
echo "${ECHO_T}$CC" >&6
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
fi
test -n "$CC" && break
done
fi
if test -z "$CC"; then
ac_ct_CC=$CC
for ac_prog in cl
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
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="$ac_prog"
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
test -n "$ac_ct_CC" && break
done
CC=$ac_ct_CC
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; }; }
# 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
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); }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files a.out 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.
# 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
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.
;;
[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
break;;
* )
break;;
esac
done
else
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; }; }
fi
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
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
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; 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
# `rm'.
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_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; }; }
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.$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. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
rm -f conftest.o conftest.obj
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&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
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
*) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
break;;
esac
done
else
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; }; }
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
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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
int
main ()
{
#ifndef __GNUC__
choke me
#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
ac_compiler_gnu=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_compiler_gnu=no
fi
rm -f 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`
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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
int
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
ac_cv_prog_cc_g=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_prog_cc_g=no
fi
rm -f 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
if test "$ac_test_CFLAGS" = set; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-g"
fi
else
if test "$GCC" = yes; then
CFLAGS="-O2"
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
else
ac_cv_prog_cc_stdc=no
ac_save_CC=$CC
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include
#include
#include
#include
/* 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);
static char *e (p, i)
char **p;
int i;
{
return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
char *s;
va_list v;
va_start (v,p);
s = g (p, va_arg (v,int));
va_end (v);
return s;
}
/* 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
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. */
int osf4_cc_array ['\x00' == 0 ? 1 : -1];
int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
int argc;
char **argv;
int
main ()
{
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__"
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
fi
rm -f conftest.err conftest.$ac_objext
done
rm -f conftest.$ac_ext conftest.$ac_objext
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 ;;
*)
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" ;;
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
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
else
cat >conftest.make <<\_ACEOF
all:
@echo 'ac_maketemp="$(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
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
SET_MAKE=
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
SET_MAKE="MAKE=${MAKE-make}"
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
else
case $STRIP in
[\\/]* | ?:[\\/]*)
ac_cv_path_STRIP="$STRIP" # 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_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
break 2
fi
done
done
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
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}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
# 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
else
# Double quotes because CPP needs to be expanded
for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
do
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# Prefer to if __STDC__ is defined, since
# 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
/* end confdefs.h. */
#ifdef __STDC__
# include
#else
# include
#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
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.$ac_ext
# OK, works on sane cases. Now check whether non-existent 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
/* 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
# 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
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.err conftest.$ac_ext
if $ac_preproc_ok; then
break
fi
done
ac_cv_prog_CPP=$CPP
fi
CPP=$ac_cv_prog_CPP
else
ac_cv_prog_CPP=$CPP
fi
echo "$as_me:$LINENO: result: $CPP" >&5
echo "${ECHO_T}$CPP" >&6
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# Prefer to if __STDC__ is defined, since
# 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
/* end confdefs.h. */
#ifdef __STDC__
# include
#else
# include
#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
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.$ac_ext
# OK, works on sane cases. Now check whether non-existent 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
/* 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
# 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
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f 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; }; }
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 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
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'
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
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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include
#include
#include
#include
int
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
ac_cv_header_stdc=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_header_stdc=no
fi
rm -f 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
/* end confdefs.h. */
#include
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "memchr" >/dev/null 2>&1; then
:
else
ac_cv_header_stdc=no
fi
rm -f conftest*
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
/* end confdefs.h. */
#include
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "free" >/dev/null 2>&1; then
:
else
ac_cv_header_stdc=no
fi
rm -f conftest*
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
:
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include
#if ((' ' & 0x0FF) == 0x020)
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#else
# define ISLOWER(c) \
(('a' <= (c) && (c) <= 'i') \
|| ('j' <= (c) && (c) <= 'r') \
|| ('s' <= (c) && (c) <= 'z'))
# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
#endif
#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int
main ()
{
int i;
for (i = 0; i < 256; i++)
if (XOR (islower (i), ISLOWER (i))
|| toupper (i) != TOUPPER (i))
exit(2);
exit (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
( exit $ac_status )
ac_cv_header_stdc=no
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
fi
fi
echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
echo "${ECHO_T}$ac_cv_header_stdc" >&6
if test $ac_cv_header_stdc = yes; then
cat >>confdefs.h <<\_ACEOF
#define STDC_HEADERS 1
_ACEOF
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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include
#include
#include
int
main ()
{
if ((struct tm *) 0)
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_header_time=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_header_time=no
fi
rm -f 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
if test $ac_cv_header_time = yes; then
cat >>confdefs.h <<\_ACEOF
#define TIME_WITH_SYS_TIME 1
_ACEOF
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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include
#include
#ifndef WEXITSTATUS
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif
#ifndef WIFEXITED
# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif
int
main ()
{
int s;
wait (&s);
s = WIFEXITED (s) ? WEXITSTATUS (s) : 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_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
fi
rm -f 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
if test $ac_cv_header_sys_wait_h = yes; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_SYS_WAIT_H 1
_ACEOF
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
cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
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
cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
int
main ()
{
/* FIXME: Include the comments suggested by Paul. */
#ifndef __cplusplus
/* Ultrix mips cc rejects this. */
typedef int charset[2];
const charset x;
/* SunOS 4.1.1 cc rejects this. */
char const *const *ccp;
char **p;
/* NEC SVR4.0.2 mips cc rejects this. */
struct point {int x, y;};
static struct point const zero = {0,0};
/* AIX XL C 1.02.0.0 rejects this.
It does not let you subtract one const X* pointer from another in
an arm of an if-expression whose if-part is not a constant
expression */
const char *g = "string";
ccp = &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;
char const *s = 0 ? (char *) 0 : (char const *) 0;
*t++ = 0;
}
{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
int x[] = {25, 17};
const int *foo = &x[0];
++foo;
}
{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
typedef const int *iptr;
iptr p = 0;
++p;
}
{ /* AIX XL C 1.02.0.0 rejects this 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;
}
{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
const int foo = 10;
}
#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
ac_cv_c_const=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_c_const=no
fi
rm -f 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
if test $ac_cv_c_const = no; then
cat >>confdefs.h <<\_ACEOF
#define const
_ACEOF
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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include
#include
int
main ()
{
struct tm *tp; tp->tm_sec;
;
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_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
fi
rm -f 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
if test $ac_cv_struct_tm = sys/time.h; then
cat >>confdefs.h <<\_ACEOF
#define TM_IN_SYS_TIME 1
_ACEOF
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
#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
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_TM_TM_ZONE 1
_ACEOF
fi
if test "$ac_cv_member_struct_tm_tm_zone" = yes; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_TM_ZONE 1
_ACEOF
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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include
#ifndef tzname /* For SGI. */
extern char *tzname[]; /* RS6000 and others reject char **tzname. */
#endif
int
main ()
{
atoi(*tzname);
;
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_var_tzname=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_var_tzname=no
fi
rm -f 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
if test $ac_cv_var_tzname = yes; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_TZNAME 1
_ACEOF
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_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
#define mode_t int
_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_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
#define pid_t int
_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_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
_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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* 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 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
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_type_signal=int
fi
rm -f 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
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
else
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 "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "uid_t" >/dev/null 2>&1; then
ac_cv_type_uid_t=yes
else
ac_cv_type_uid_t=no
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
if test $ac_cv_type_uid_t = no; then
cat >>confdefs.h <<\_ACEOF
#define uid_t int
_ACEOF
cat >>confdefs.h <<\_ACEOF
#define gid_t int
_ACEOF
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
else
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
/* end confdefs.h. */
/* Thanks to Mike Rendell for this test. */
#include
#define NGID 256
#undef MAX
#define MAX(x, y) ((x) > (y) ? (x) : (y))
int
main ()
{
gid_t gidset[NGID];
int i, n;
union { gid_t gval; long lval; } val;
val.lval = -1;
for (i = 0; i < NGID; i++)
gidset[i] = val.gval;
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);
}
_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
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
( 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
/* end confdefs.h. */
#include
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "getgroups.*int.*gid_t" >/dev/null 2>&1; then
ac_cv_type_getgroups=gid_t
else
ac_cv_type_getgroups=int
fi
rm -f conftest*
fi
fi
echo "$as_me:$LINENO: result: $ac_cv_type_getgroups" >&5
echo "${ECHO_T}$ac_cv_type_getgroups" >&6
cat >>confdefs.h <<_ACEOF
#define GETGROUPS_T $ac_cv_type_getgroups
_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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include
va_list ap1,ap2;
int
main ()
{
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
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
fi
rm -f 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
if test x"$ac_cv_HAVE_VA_COPY" = x"yes"; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_VA_COPY 1
_ACEOF
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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include
va_list ap1,ap2;
int
main ()
{
__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
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
fi
rm -f 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
if test x"$ac_cv_HAVE___VA_COPY" = x"yes"; then
cat >>confdefs.h <<\_ACEOF
#define HAVE___VA_COPY 1
_ACEOF
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
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_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
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
else
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
/* end confdefs.h. */
#include
#include
void foo(const char *format, ...) {
va_list ap;
int len;
char buf[5];
va_start(ap, format);
len = vsnprintf(buf, 0, format, ap);
va_end(ap);
if (len != 5) exit(1);
va_start(ap, format);
len = vsnprintf(0, 0, format, ap);
va_end(ap);
if (len != 5) exit(1);
if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(1);
exit(0);
}
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
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
( 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
if test x"$ac_cv_HAVE_C99_VSNPRINTF" = x"yes"; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_C99_VSNPRINTF 1
_ACEOF
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
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
/* 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 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="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
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. */
/* 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
fi
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"
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
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
/* 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 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="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
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. */
/* 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
fi
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"
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
cat >>confdefs.h <<_ACEOF
#define `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
/* end confdefs.h. */
#include
#include
#include
int
main ()
{
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"
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
fi
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
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
/* 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 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="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
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. */
/* 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
fi
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"
else
echo "Error: nanosleep() needed for timing operations."
exit 1
fi
# 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
else
nagios_user=nagios
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
else
nagios_grp=nagios
fi;
cat >>confdefs.h <<_ACEOF
#define DEFAULT_NAGIOS_USER "$nagios_user"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define DEFAULT_NAGIOS_GROUP "$nagios_grp"
_ACEOF
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
else
command_user=$nagios_user
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
else
command_grp=$nagios_grp
fi;
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
else
MAIL_PROG=no
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
else
case $MAIL_PROG in
[\\/]* | ?:[\\/]*)
ac_cv_path_MAIL_PROG="$MAIL_PROG" # 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_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
break 2
fi
done
done
;;
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
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
fi
fi
if test x$MAIL_PROG = x; then
MAIL_PROG="/bin/mail"
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
else
HTTPD_CONF=no
fi;
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/apache/conf.d; then
HTTPD_CONF="/etc/apache/conf.d"
else
HTTPD_CONF="/etc/httpd/conf.d"
fi
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
else
CHECKRESULTDIR=no
fi;
if test x$CHECKRESULTDIR = xno; then
CHECKRESULTDIR="$localstatedir/spool/checkresults"
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
else
TMPDIR=no
fi;
if test x$TMPDIR = xno; then
TMPDIR="/tmp"
fi
init_dir=/etc/rc.d/init.d
if test -d /etc/rc.d/init.d; then
init_dir="/etc/rc.d/init.d"
elif test -d /usr/local/etc/rc.d; then
init_dir="/usr/local/etc/rc.d"
elif test -d /etc/rc.d; then
init_dir="/etc/rc.d"
elif test -d /etc/init.d; then
init_dir="/etc/init.d"
elif test -d /sbin/init.d; then
init_dir="/sbin/init.d"
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-lockfile or --without-lockfile was given.
if test "${with_lockfile+set}" = set; then
withval="$with_lockfile"
lockfile=$withval
else
lockfile=$localstatedir/nagios.lock
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
_ACEOF
XSDC="xsddefault.c"
XSDH="xsddefault.h"
XSDCOMMENT="Default (text file)"
echo "We'll use default routines (in xdata/xsddefault.*) for status data I/O..."
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..."
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..."
cat >>confdefs.h <<_ACEOF
#define USE_XODTEMPLATE
_ACEOF
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
TRYSTATUSMAP=yep
# Check whether --enable-statusmap or --disable-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;
if test x$TRYSTATUSWRL = xyep; then
cat >>confdefs.h <<_ACEOF
#define USE_STATUSWRL
_ACEOF
CGIEXTRAS="$CGIEXTRAS statuswrl.cgi"
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
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
/* end confdefs.h. */
int
main ()
{
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
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
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_iconv_main" >&5
echo "${ECHO_T}$ac_cv_lib_iconv_main" >&6
if test $ac_cv_lib_iconv_main = yes; 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
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
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
/* 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
builtin and then its argument prototype would still apply. */
char gdImagePng();
int
main ()
{
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
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"
fi
rm -f 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
GDLIBFOUND=yep
GDLIBS="-lgd -lttf -lpng -ljpeg -lz -lm"
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}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
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
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
/* 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
builtin and then its argument prototype would still apply. */
char gdImagePng();
int
main ()
{
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
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"
fi
rm -f 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
GDLIBFOUND=yep
GDLIBS="-lgd $ICONV -lpng -ljpeg -lz -lm"
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}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
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
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
/* 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
builtin and then its argument prototype would still apply. */
char gdImagePng();
int
main ()
{
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
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"
fi
rm -f 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
GDLIBFOUND=yep
GDLIBS="-lgd $ICONV -lz -lm -lpng"
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}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
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
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
/* 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
builtin and then its argument prototype would still apply. */
char gdImagePng();
int
main ()
{
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
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"
fi
rm -f 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
GDLIBFOUND=yep
GDLIBS="-lgd $ICONV -lpng -lz -lm"
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
:
fi
fi
if test x$GDLIBFOUND = x; then
echo ""
echo ""
echo "*** GD, PNG, and/or JPEG libraries could not be located... *********"
echo ""
echo "Boutell's GD library is required to compile the statusmap, trends"
echo "and histogram CGIs. Get it from http://www.boutell.com/gd/, compile"
echo "it, and use the --with-gd-lib and --with-gd-inc arguments to specify"
echo "the locations of the GD library and include files."
echo ""
echo "NOTE: In addition to the gd-devel library, you'll also need to make"
echo " sure you have the png-devel and jpeg-devel libraries installed"
echo " on your system."
echo ""
echo "NOTE: After you install the necessary libraries on your system:"
echo " 1. Make sure /etc/ld.so.conf has an entry for the directory in"
echo " which the GD, PNG, and JPEG libraries are installed."
echo " 2. Run 'ldconfig' to update the run-time linker options."
echo " 3. Run 'make clean' in the Nagios distribution to clean out"
echo " any old references to your previous compile."
echo " 4. Rerun the configure script."
echo ""
echo "NOTE: If you can't get the configure script to recognize the GD libs"
echo " on your system, get over it and move on to other things. The"
echo " CGIs that use the GD libs are just a small part of the entire"
echo " Nagios package. Get everything else working first and then"
echo " revisit the problem. Make sure to check the nagios-users"
echo " mailing list archives for possible solutions to GD library"
echo " problems when you resume your troubleshooting."
echo ""
echo "********************************************************************"
echo ""
echo ""
else
echo "GD library was found!"
if test x$TRYSTATUSMAP = xyep; then
cat >>confdefs.h <<_ACEOF
#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
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
/* 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 gdImageCreateTrueColor ();
int
main ()
{
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
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
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_gd_gdImageCreateTrueColor" >&5
echo "${ECHO_T}$ac_cv_lib_gd_gdImageCreateTrueColor" >&6
if test $ac_cv_lib_gd_gdImageCreateTrueColor = yes; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_GDIMAGECREATETRUECOLOR 1
_ACEOF
fi
fi
cat >>confdefs.h <<_ACEOF
#define USE_TRENDS
_ACEOF
CGIEXTRAS="$CGIEXTRAS trends.cgi"
cat >>confdefs.h <<_ACEOF
#define USE_HISTOGRAM
_ACEOF
CGIEXTRAS="$CGIEXTRAS histogram.cgi"
fi
fi
# Check whether --with-cgiurl or --without-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
else
htmurl=/nagios
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
else
USE_NANOSLEEP=yes
fi;
if test x$USE_NANOSLEEP = xyes; then
cat >>confdefs.h <<_ACEOF
#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
else
USE_EVENTBROKER=yes
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_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
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
/* 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 lt_dlinit ();
int
main ()
{
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
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
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_ltdl_lt_dlinit" >&5
echo "${ECHO_T}$ac_cv_lib_ltdl_lt_dlinit" >&6
if test $ac_cv_lib_ltdl_lt_dlinit = yes; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_LTDL_H
_ACEOF
some_dl_found="yes"
BROKERLIBS="$BROKERLIBS -lltdl"
fi
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_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
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
/* 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 dlopen ();
int
main ()
{
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
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
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_dl_dlopen" >&5
echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
if test $ac_cv_lib_dl_dlopen = yes; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_DLFCN_H
_ACEOF
some_dl_found="yes"
BROKERLIBS="$BROKERLIBS -ldl"
fi
fi
fi
# Check how to export functions from the broker executable, needed
# when dynamically loaded drivers are loaded (so that they can find
# broker functions).
# OS'es with ELF executables using the GNU linker (Linux and recent *BSD,
# in rare cases Solaris) typically need '-Wl,-export-dynamic' (i.e. pass
# -export-dynamic to the linker - also known as -rdynamic and some other
# variants); some sysVr4 system(s) instead need(s) '-Wl,-Bexport'.
# 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
case $host_os in
aix4*|aix5*)
BROKER_LDFLAGS="$BROKER_LDFLAGS -Wl,-bexpall,-brtl"
;;
bsdi*)
BROKER_LDFLAGS="$BROKER_LDFLAGS -rdynamic"
;;
*)
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
/* end confdefs.h. */
int
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
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
/* end confdefs.h. */
int
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
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
fi
rm -f 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
LDFLAGS="$save_ldflags"
;;
esac
test "x$BROKER_LDFLAGS" != x && echo "$as_me:$LINENO: result: $BROKER_LDFLAGS" >&5
echo "${ECHO_T}$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
case $host_os in
solaris2*|sysv4*)
MOD_LDFLAGS="-G"
;;
aix4*|aix5*)
#MOD_LDFLAGS="-G -bnoentry -bexpall"
MOD_LDFLAGS="-G -bM:SRE -bnoentry -bexpall"
;;
freebsd2*)
# Non-ELF GNU linker
MOD_LDFLAGS="-Bshareable"
;;
darwin*)
# Mach-O linker, a shared lib and a loadable
# object file is not the same thing.
MOD_LDFLAGS="-bundle -flat_namespace -undefined suppress"
MOD_CFLAGS="$MOD_CFLAGS -fno-common"
;;
linux* | k*bsd*-gnu*)
# assume GNU linker and ELF
MOD_LDFLAGS="-shared"
MOD_CFLAGS="-fPIC"
;;
freebsd*)
MOD_LDFLAGS="-shared"
MOD_CFLAGS="-fPIC"
;;
*)
# assume GNU linker and ELF
MOD_LDFLAGS="-shared"
;;
esac
echo "$as_me:$LINENO: result: $MOD_LDFLAGS" >&5
echo "${ECHO_T}$MOD_LDFLAGS" >&6
cat >>confdefs.h <<_ACEOF
#define USE_EVENT_BROKER
_ACEOF
BROKER_O="broker.o nebmods.o"
BROKER_H="../include/broker.h ../include/nebmods.h ../include/nebmodules.h ../include/nebcallbacks.h ../include/neberrors.h"
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"
cygwin=$enableval
fi;
if test x$cygwin = xyes; then
CFLAGS="${CFLAGS} -DCYGWIN"
nagios_name=nagios.exe;
nagiostats_name=nagiostats.exe;
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
else
case $PATH_TO_TRACEROUTE in
[\\/]* | ?:[\\/]*)
ac_cv_path_PATH_TO_TRACEROUTE="$PATH_TO_TRACEROUTE" # 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_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
break 2
fi
done
done
;;
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
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
fi
cat >>confdefs.h <<_ACEOF
#define TRACEROUTE_COMMAND "$PATH_TO_TRACEROUTE"
_ACEOF
VERSION=$PKG_VERSION
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
/* end confdefs.h. */
#ifdef __STDC__
#include
#include
#include
#else
#include
#include
#include
#endif
int
main ()
{
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
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
fi
rm -f 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
else
enable_libtap=no
fi;
#Disabled for moment
#AM_CONDITIONAL([USE_LIBTAP_LOCAL],[test "$enable_libtap" = "yes"])
# Disabled for moment
# If not local, check if we can use the system one
#if test "$enable_libtap" != "yes" ; then
# dnl Check for libtap, to run perl-like tests
# AC_CHECK_LIB(tap, plan_tests,
# enable_libtap="yes"
# )
#fi
# Finally, define tests if we use libtap
if test "$enable_libtap" = "yes" ; then
subdirs="$subdirs tap"
USE_LIBTAP=yes
else
USE_LIBTAP=no
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
else
case $PERL in
[\\/]* | ?:[\\/]*)
ac_cv_path_PERL="$PERL" # 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_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
break 2
fi
done
done
;;
esac
fi
PERL=$ac_cv_path_PERL
if test -n "$PERL"; then
echo "$as_me:$LINENO: result: $PERL" >&5
echo "${ECHO_T}$PERL" >&6
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}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"
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=
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'
done
LIBOBJS=$ac_libobjs
LTLIBOBJS=$ac_ltlibobjs
: ${CONFIG_STATUS=./config.status}
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
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.
debug=false
ac_cs_recheck=false
ac_cs_silent=false
SHELL=\${CONFIG_SHELL-$SHELL}
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
## --------------------- ##
## M4sh Initialization. ##
## --------------------- ##
# Be Bourne compatible
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
# 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
else
as_unset=false
fi
# Work around bugs in pre-3.0 UWIN ksh.
$as_unset ENV MAIL MAILPATH
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
# Required to use basename.
if expr a : '\(a\)' >/dev/null 2>&1; then
as_expr=expr
else
as_expr=false
fi
if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
# Name of the executable.
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'`
# PATH needs CR, and LINENO needs CR and PATH.
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
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= ;;
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
as_ln_s='ln -s'
fi
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -p'
fi
rm -f conf$$ conf$$.exe conf$$.file
if mkdir -p . 2>/dev/null; then
as_mkdir_p=:
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
as_executable_p="test -f"
# 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'"
# Sed expression to map a string onto a valid variable name.
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
# Open the log real soon, 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
This file was extended by $as_me, which was
generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
CONFIG_LINKS = $CONFIG_LINKS
CONFIG_COMMANDS = $CONFIG_COMMANDS
$ $0 $@
_CSEOF
echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
echo >&5
_ACEOF
# Files that config.status was made for.
if test -n "$ac_config_files"; then
echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
fi
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
ac_cs_usage="\
\`$as_me' instantiates files from templates according to the
current configuration.
Usage: $0 [OPTIONS] [FILE]...
-h, --help print this help, then exit
-V, --version print version number, then exit
-q, --quiet 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
Configuration files:
$config_files
Configuration headers:
$config_headers
Report bugs to ."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
config.status
configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
Copyright (C) 2003 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"
_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.
ac_need_defaults=:
while test $# != 0
do
case $1 in
--*=*)
ac_option=`expr "x$1" : 'x\([^=]*\)='`
ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
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 )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
CONFIG_FILES="$CONFIG_FILES $ac_optarg"
ac_need_defaults=false;;
--header | --heade | --head | --hea )
$ac_shift
CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
ac_need_defaults=false;;
-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; }; } ;;
*) ac_config_targets="$ac_config_targets $1" ;;
esac
shift
done
ac_configure_extra_args=
if $ac_cs_silent; then
exec 6>/dev/null
ac_configure_extra_args="$ac_configure_extra_args --silent"
fi
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
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
fi
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
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; }; };;
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
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
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,
# creating and moving files from /tmp can sometimes cause problems.
# Create a temporary directory, and hook for its removal unless debugging.
$debug ||
{
trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
trap '{ (exit 1); 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=./confstat$$-$RANDOM
(umask 077 && mkdir $tmp)
} ||
{
echo "$me: cannot create a temporary directory in ." >&2
{ (exit 1); exit 1; }
}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
#
# 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
fi # test -n "$CONFIG_FILES"
_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 ;;
esac
# Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
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; }; }; }
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 $srcdir in
.) # No --srcdir option. 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_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;;
esac
case $INSTALL in
[\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
*) ac_INSTALL=$ac_top_builddir$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
$extrasub
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
: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
done
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
#
# 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".
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
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;}
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
fi
else
cat $tmp/config.h
rm -f $tmp/config.h
fi
done
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
{ (exit 0); exit 0; }
_ACEOF
chmod +x $CONFIG_STATUS
ac_clean_files=$ac_clean_files_save
# configure is writing to config.log, and then calls config.status.
# config.status does its own redirection, appending to config.log.
# Unfortunately, on DOS this fails, as config.log is still kept open
# by configure, so config.status won't be able to write to it; its
# output is simply discarded. So we exec the FD to /dev/null,
# effectively closing config.log, so it can be properly (re)opened and
# appended to by config.status. When coming back to configure, we
# need to make the FD available again.
if test "$no_create" != yes; then
ac_cs_success=:
ac_config_status_args=
test "$silent" = yes &&
ac_config_status_args="$ac_config_status_args --quiet"
exec 5>/dev/null
$SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
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; }
fi
#
# CONFIG_SUBDIRS section.
#
if test "$no_recursion" != yes; then
# Remove --cache-file and --srcdir arguments so they do not pile up.
ac_sub_configure_args=
ac_prev=
for ac_arg in $ac_configure_args; do
if test -n "$ac_prev"; then
ac_prev=
continue
fi
case $ac_arg in
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \
| --c=*)
;;
--config-cache | -C)
;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
;;
*) ac_sub_configure_args="$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_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; }; }; }
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 $srcdir in
.) # No --srcdir option. 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_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;;
esac
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
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;}
ac_sub_configure=
fi
# The recursion is here.
if test -n "$ac_sub_configure"; then
# 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 ;;
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;}
# 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; }; }
fi
cd $ac_popdir
done
fi
perl subst include/locations.h
perl subst html/config.inc.php
echo ""
echo "Creating sample config files in sample-config/ ..."
perl subst sample-config/nagios.cfg
perl subst sample-config/cgi.cfg
perl subst sample-config/resource.cfg
perl subst sample-config/httpd.conf
perl subst sample-config/mrtg.cfg
perl subst sample-config/template-object/templates.cfg
perl subst sample-config/template-object/commands.cfg
perl subst sample-config/template-object/timeperiods.cfg
perl subst sample-config/template-object/contacts.cfg
perl subst sample-config/template-object/localhost.cfg
perl subst sample-config/template-object/windows.cfg
perl subst sample-config/template-object/printer.cfg
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
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
if test x$USE_EVENTBROKER = xyes; then
echo "$as_me:$LINENO: result: Event Broker: yes" >&5
echo "${ECHO_T} Event Broker: yes" >&6
else
echo "$as_me:$LINENO: result: Event Broker: no" >&5
echo "${ECHO_T} 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
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
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 ""
nagios/configure.in 0000664 0000000 0000000 00000067232 12210155146 0014656 0 ustar 00root root 0000000 0000000 dnl Process this -*-m4-*- file with autoconf to produce a configure script.
dnl Disable caching
define([AC_CACHE_LOAD],)
define([AC_CACHE_SAVE],)
AC_INIT(base/nagios.c)
AC_CONFIG_HEADER(include/config.h include/snprintf.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"
dnl Figure out how to invoke "install" and what install options to use.
AC_PROG_INSTALL
AC_SUBST(INSTALL)
dnl What OS are we running?
AC_CANONICAL_HOST
dnl Checks for programs.
AC_PROG_CC
AC_PROG_MAKE_SET
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)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_STRUCT_TM
AC_STRUCT_TIMEZONE
AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_SIGNAL
AC_TYPE_GETGROUPS
dnl Check for asprintf() and friends...
AC_CACHE_CHECK([for va_copy],ac_cv_HAVE_VA_COPY,[
AC_TRY_LINK([#include
va_list ap1,ap2;], [va_copy(ap1,ap2);],
ac_cv_HAVE_VA_COPY=yes,
ac_cv_HAVE_VA_COPY=no)])
if test x"$ac_cv_HAVE_VA_COPY" = x"yes"; then
AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available])
else
AC_CACHE_CHECK([for __va_copy],ac_cv_HAVE___VA_COPY,[
AC_TRY_LINK([#include
va_list ap1,ap2;], [__va_copy(ap1,ap2);],
ac_cv_HAVE___VA_COPY=yes,
ac_cv_HAVE___VA_COPY=no)])
if test x"$ac_cv_HAVE___VA_COPY" = x"yes"; then
AC_DEFINE(HAVE___VA_COPY,1,[Whether __va_copy() is available])
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_CACHE_CHECK([for C99 vsnprintf],ac_cv_HAVE_C99_VSNPRINTF,[
AC_TRY_RUN([
#include
#include
void foo(const char *format, ...) {
va_list ap;
int len;
char buf[5];
va_start(ap, format);
len = vsnprintf(buf, 0, format, ap);
va_end(ap);
if (len != 5) exit(1);
va_start(ap, format);
len = vsnprintf(0, 0, format, ap);
va_end(ap);
if (len != 5) exit(1);
if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(1);
exit(0);
}
main() { foo("hello"); }
],
ac_cv_HAVE_C99_VSNPRINTF=yes,ac_cv_HAVE_C99_VSNPRINTF=no,ac_cv_HAVE_C99_VSNPRINTF=cross)])
if test x"$ac_cv_HAVE_C99_VSNPRINTF" = x"yes"; then
AC_DEFINE(HAVE_C99_VSNPRINTF,1,[Define if system has C99 compatible vsnprintf])
fi
dnl AC_CHECK_FUNC(snprintf,AC_DEFINE(HAVE_SNPRINTF),SNPRINTF_O=../common/snprintf.o)
AC_SUBST(SNPRINTF_O)
dnl Checks for library functions.
AC_SEARCH_LIBS([getservbyname],[nsl],
[if test "$ac_cv_search_getservbyname" != "none required"; then
SOCKETLIBS="$SOCKETLIBS -lnsl"
fi])
AC_SEARCH_LIBS([connect],[socket],
[if test "$ac_cv_search_connect" != "none required"; then
SOCKETLIBS="$SOCKETLIBS -lsocket"
fi])
AC_SUBST(SOCKETLIBS)
AC_CHECK_FUNCS(initgroups setenv strdup strstr strtoul unsetenv)
AC_MSG_CHECKING(for type of socket size)
AC_TRY_COMPILE([#include
#include
#include
],
[int a = send(1, (const void *) 0, (size_t) 0, (int) 0);],
[AC_DEFINE(SOCKET_SIZE_TYPE, size_t, [typedef for socket size]) AC_MSG_RESULT(size_t)],
[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
])
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)
AC_SUBST(nagios_grp)
AC_DEFINE_UNQUOTED(DEFAULT_NAGIOS_USER,"$nagios_user",[user name to run nagios])
AC_DEFINE_UNQUOTED(DEFAULT_NAGIOS_GROUP,"$nagios_grp",[group name to run nagios])
INSTALL_OPTS="-o $nagios_user -g $nagios_grp"
AC_SUBST(INSTALL_OPTS)
AC_ARG_WITH(command_user,AC_HELP_STRING([--with-command-user=],[sets user name for command access]),command_user=$withval,command_user=$nagios_user)
AC_ARG_WITH(command_group,AC_HELP_STRING([--with-command-group=],[sets group name for command access]),command_grp=$withval,command_grp=$nagios_grp)
AC_SUBST(command_user)
AC_SUBST(command_grp)
COMMAND_OPTS="-o $command_user -g $command_grp"
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)
if test x$MAIL_PROG = xno; then
AC_PATH_PROG(MAIL_PROG,mail)
fi
dnl Fix for systems that don't (yet) have mail/mailx installed...
if test x$MAIL_PROG = x; then
MAIL_PROG="/bin/mail"
fi
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)
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/apache/conf.d; then
HTTPD_CONF="/etc/apache/conf.d"
else
HTTPD_CONF="/etc/httpd/conf.d"
fi
fi
AC_SUBST(HTTPD_CONF)
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)
if test x$CHECKRESULTDIR = xno; then
CHECKRESULTDIR="$localstatedir/spool/checkresults"
fi
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)
if test x$TMPDIR = xno; then
TMPDIR="/tmp"
fi
AC_SUBST(TMPDIR)
dnl Check for location of init scripts
init_dir=/etc/rc.d/init.d
if test -d /etc/rc.d/init.d; then
init_dir="/etc/rc.d/init.d"
elif test -d /usr/local/etc/rc.d; then
init_dir="/usr/local/etc/rc.d"
elif test -d /etc/rc.d; then
init_dir="/etc/rc.d"
elif test -d /etc/init.d; then
init_dir="/etc/init.d"
elif test -d /sbin/init.d; then
init_dir="/sbin/init.d"
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_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_SUBST(lockfile)
dnl Default xdata routines...
XSDTYPE=default
XCDTYPE=default
XRDTYPE=default
XODTYPE=template
XPDTYPE=default
XDDTYPE=default
XSDCOMMENT=
XCDCOMMENT=
XRDCOMMENT=
XODCOMMENT=
XPDCOMMENT=
XDDCOMMENT=
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)
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}"
])
TRYGD=yep
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)
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)
if test x$TRYSTATUSWRL = xyep; then
AC_DEFINE_UNQUOTED(USE_STATUSWRL,,[statuswrl CGI enabled by default, unless users chooses not to use it])
CGIEXTRAS="$CGIEXTRAS statuswrl.cgi"
fi
dnl JMD_CHECK_LIB_ORDER(LIBRARY, FUNCTION, ORDER [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND
dnl [, OTHER-LIBRARIES]]])
AC_DEFUN([JMD_CHECK_LIB_ORDER],
[AC_MSG_CHECKING([for $2 in -l$1 (order $3)])
dnl Use a cache variable name containing both the library and function name,
dnl because the test really is for library $1 defining function $2, not
dnl just for library $1. Separate tests with the same $1 and different $2s
dnl may have different results.
ac_lib_var=`echo $1['_']$2['_']$3 | sed 'y%./+-%__p_%'`
AC_CACHE_VAL(ac_cv_lib_$ac_lib_var,
[ac_save_LIBS="$LIBS"
LIBS="-l$1 $6 $LIBS"
AC_TRY_LINK(dnl
ifelse([AC_LANG], [FORTRAN77], ,
ifelse([$2], [main], , dnl Avoid conflicting decl of main.
[/* Override any gcc2 internal prototype to avoid an error. */
]ifelse([AC_LANG], CPLUSPLUS, [#ifdef __cplusplus
extern "C"
#endif
])dnl
[/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char $2();
])),
[$2()],
eval "ac_cv_lib_$ac_lib_var=yes",
eval "ac_cv_lib_$ac_lib_var=no")
LIBS="$ac_save_LIBS"
])dnl
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
AC_MSG_RESULT(yes)
ifelse([$4], ,
[changequote(, )dnl
ac_tr_lib=HAVE_LIB`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
changequote([, ])dnl
AC_DEFINE_UNQUOTED($ac_tr_lib)
LIBS="-l$1 $LIBS"
], [$4])
else
AC_MSG_RESULT(no)
ifelse([$5], , , [$5
])dnl
fi
])
dnl Should we try and detect the GD libs?
if test x$TRYGD = xyep; then
dnl libiconv is required on some systems - tack it on if found
AC_CHECK_LIB(iconv,main,ICONV=-liconv,)
dnl See if the GD lib is available and supports PNG images...
dnl GD > 1.8.3 requires the TrueType library to be present as well, so test for that first...
JMD_CHECK_LIB_ORDER(gd,gdImagePng,1,[
GDLIBFOUND=yep
GDLIBS="-lgd -lttf -lpng -ljpeg -lz -lm"
],:,[-lttf -lpng -ljpeg -lz -lm])
dnl GD > 1.8.1 requires the jpeg library to be present as well, so test for that...
if test x$GDLIBFOUND = x; then
JMD_CHECK_LIB_ORDER(gd,gdImagePng,2,[
GDLIBFOUND=yep
GDLIBS="-lgd $ICONV -lpng -ljpeg -lz -lm"
],:,[$ICONV -lpng -ljpeg -lz -lm])
fi
dnl If we failed the first test, try without jpeg library
if test x$GDLIBFOUND = x; then
JMD_CHECK_LIB_ORDER(gd,gdImagePng,3,[
GDLIBFOUND=yep
GDLIBS="-lgd $ICONV -lz -lm -lpng"
],:,[$ICONV -lz -lm -lpng])
fi
dnl We failed again, so try a different library ordering (without jpeg libs)
if test x$GDLIBFOUND = x; then
JMD_CHECK_LIB_ORDER(gd,gdImagePng,4,[
GDLIBFOUND=yep
GDLIBS="-lgd $ICONV -lpng -lz -lm"
],:,[$ICONV -lpng -lz -lm])
fi
dnl Did we find the necessary GD libraries?
if test x$GDLIBFOUND = x; then
echo ""
echo ""
echo "*** GD, PNG, and/or JPEG libraries could not be located... *********"
echo ""
echo "Boutell's GD library is required to compile the statusmap, trends"
echo "and histogram CGIs. Get it from http://www.boutell.com/gd/, compile"
echo "it, and use the --with-gd-lib and --with-gd-inc arguments to specify"
echo "the locations of the GD library and include files."
echo ""
echo "NOTE: In addition to the gd-devel library, you'll also need to make"
echo " sure you have the png-devel and jpeg-devel libraries installed"
echo " on your system."
echo ""
echo "NOTE: After you install the necessary libraries on your system:"
echo " 1. Make sure /etc/ld.so.conf has an entry for the directory in"
echo " which the GD, PNG, and JPEG libraries are installed."
echo " 2. Run 'ldconfig' to update the run-time linker options."
echo " 3. Run 'make clean' in the Nagios distribution to clean out"
echo " any old references to your previous compile."
echo " 4. Rerun the configure script."
echo ""
echo "NOTE: If you can't get the configure script to recognize the GD libs"
echo " on your system, get over it and move on to other things. The"
echo " CGIs that use the GD libs are just a small part of the entire"
echo " Nagios package. Get everything else working first and then"
echo " revisit the problem. Make sure to check the nagios-users"
echo " mailing list archives for possible solutions to GD library"
echo " problems when you resume your troubleshooting."
echo ""
echo "********************************************************************"
echo ""
echo ""
dnl We found the GD lib!
else
echo "GD library was found!"
if test x$TRYSTATUSMAP = xyep; then
AC_DEFINE_UNQUOTED(USE_STATUSMAP,,[defined if the user chose to include status map])
CGIEXTRAS="$CGIEXTRAS statusmap.cgi"
AC_CHECK_LIB(gd,gdImageCreateTrueColor,
AC_DEFINE(HAVE_GDIMAGECREATETRUECOLOR,1,
[Define if your gd library has gdImageCreateTrueColor]))
fi
dnl compile trends CGI
AC_DEFINE_UNQUOTED(USE_TRENDS,,[compile trends CGI])
CGIEXTRAS="$CGIEXTRAS trends.cgi"
dnl compile histogram CGI
AC_DEFINE_UNQUOTED(USE_HISTOGRAM,,[compile histogram CGI])
CGIEXTRAS="$CGIEXTRAS histogram.cgi"
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_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)
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)
BROKER_LDFLAGS=""
BROKERLIBS="";
some_dl_found="no";
if test x$USE_EVENTBROKER = xyes; then
dnl Which loader library should we use? libtdl or dl?
dnl Hopefully this will be portable and not give us headaches...
AC_CHECK_HEADER(ltdl.h,[
AC_CHECK_LIB(ltdl,lt_dlinit,[
AC_DEFINE(HAVE_LTDL_H,,[Which loader library should we use? libtdl or dl?])
some_dl_found="yes"
BROKERLIBS="$BROKERLIBS -lltdl"
])
])
if test "x$some_dl_found" != xyes; then
AC_CHECK_HEADER(dlfcn.h,[
AC_CHECK_LIB(dl,dlopen,[
AC_DEFINE(HAVE_DLFCN_H,,[Which loader library should we use? libtdl or dl?])
some_dl_found="yes"
BROKERLIBS="$BROKERLIBS -ldl"
])
])
fi
dnl - Modified from www.erlang.org
# Check how to export functions from the broker executable, needed
# when dynamically loaded drivers are loaded (so that they can find
# broker functions).
# OS'es with ELF executables using the GNU linker (Linux and recent *BSD,
# in rare cases Solaris) typically need '-Wl,-export-dynamic' (i.e. pass
# -export-dynamic to the linker - also known as -rdynamic and some other
# variants); some sysVr4 system(s) instead need(s) '-Wl,-Bexport'.
# 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.
AC_MSG_CHECKING(for extra flags needed to export symbols)
case $host_os in
aix4*|aix5*)
BROKER_LDFLAGS="$BROKER_LDFLAGS -Wl,-bexpall,-brtl"
;;
bsdi*)
BROKER_LDFLAGS="$BROKER_LDFLAGS -rdynamic"
;;
*)
save_ldflags="$LDFLAGS"
LDFLAGS=-Wl,-export-dynamic
AC_TRY_LINK(,,[BROKER_LDFLAGS="$BROKER_LDFLAGS -Wl,-export-dynamic"], [
LDFLAGS=-Wl,-Bexport
AC_TRY_LINK(,,[BROKER_LDFLAGS="$BROKER_LDFLAGS -Wl,-Bexport"],
AC_MSG_RESULT(none))])
LDFLAGS="$save_ldflags"
;;
esac
AC_SUBST(BROKER_LDFLAGS)
AC_SUBST(BROKERLIBS)
test "x$BROKER_LDFLAGS" != x && AC_MSG_RESULT([$BROKER_LDFLAGS])
dnl - Modified version from www.erlang.org
dnl - Some 12/15/05 mods made after reading http://xaxxon.slackworks.com/phuku/dl.html
AC_MSG_CHECKING(for linker flags for loadable modules)
case $host_os in
solaris2*|sysv4*)
MOD_LDFLAGS="-G"
;;
aix4*|aix5*)
#MOD_LDFLAGS="-G -bnoentry -bexpall"
MOD_LDFLAGS="-G -bM:SRE -bnoentry -bexpall"
;;
freebsd2*)
# Non-ELF GNU linker
MOD_LDFLAGS="-Bshareable"
;;
darwin*)
# Mach-O linker, a shared lib and a loadable
# object file is not the same thing.
MOD_LDFLAGS="-bundle -flat_namespace -undefined suppress"
MOD_CFLAGS="$MOD_CFLAGS -fno-common"
;;
linux* | k*bsd*-gnu*)
# assume GNU linker and ELF
MOD_LDFLAGS="-shared"
MOD_CFLAGS="-fPIC"
;;
freebsd*)
MOD_LDFLAGS="-shared"
MOD_CFLAGS="-fPIC"
;;
*)
# assume GNU linker and ELF
MOD_LDFLAGS="-shared"
;;
esac
AC_MSG_RESULT([$MOD_LDFLAGS])
AC_SUBST(MOD_CFLAGS)
AC_SUBST(MOD_LDFLAGS)
AC_DEFINE_UNQUOTED(USE_EVENT_BROKER,,[defined to bring in the event broker objects])
BROKER_O="broker.o nebmods.o"
AC_SUBST(BROKER_O)
BROKER_H="../include/broker.h ../include/nebmods.h ../include/nebmodules.h ../include/nebcallbacks.h ../include/neberrors.h"
AC_SUBST(BROKER_H)
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
])
if test x$cygwin = xyes; then
CFLAGS="${CFLAGS} -DCYGWIN"
nagios_name=nagios.exe;
nagiostats_name=nagiostats.exe;
fi
AC_SUBST(nagios_name)
AC_SUBST(nagiostats_name)
dnl Should predictive failure routines be compiled in?
dnl AC_ARG_ENABLE(failure-prediction,--enable-failure-prediction will enable integration with failure prediction module (NOT HERE YET!),[
dnl AC_DEFINE_UNQUOTED(PREDICT_FAILURES)
dnl BASEEXTRALIBS="$BASEEXTRALIBS \$(FDATALIBS)"
dnl echo "Failure prediction routines (incomplete!) will be compiled in..."
dnl ])
dnl Find traceroute
AC_PATH_PROG(PATH_TO_TRACEROUTE,traceroute)
AC_DEFINE_UNQUOTED(TRACEROUTE_COMMAND,"$PATH_TO_TRACEROUTE",[traceroute command to use])
dnl Package directory for Solaris pkgmk (and other OSs, eventually)
dnl VERSION=`grep 1.0 include/common.h | cut -d ' ' -f 3 | sed 's/"//g'`
VERSION=$PKG_VERSION
PACKDIR=`pwd`/pkg
AC_SUBST(PACKDIR)
AC_SUBST(VERSION)
AC_MSG_CHECKING(for type va_list)
AC_TRY_COMPILE([#ifdef __STDC__
#include
#include
#include
#else
#include
#include
#include
#endif],
[va_list args;],
[AC_MSG_RESULT(yes)],
[AC_DEFINE(NEED_VA_LIST,,[defined if va_list fails to compile]) AC_MSG_RESULT(no)])
dnl Check if we should build local libtap
dnl From Nagios Plugins
dnl Have disabled autodetection of system library until later
AC_ARG_ENABLE(libtap,
AC_HELP_STRING([--enable-libtap],
[Enable built-in libtap for unit-testing (default: no).]),
[enable_libtap=$enableval],
[enable_libtap=no])
#Disabled for moment
#AM_CONDITIONAL([USE_LIBTAP_LOCAL],[test "$enable_libtap" = "yes"])
# Disabled for moment
# If not local, check if we can use the system one
#if test "$enable_libtap" != "yes" ; then
# dnl Check for libtap, to run perl-like tests
# AC_CHECK_LIB(tap, plan_tests,
# enable_libtap="yes"
# )
#fi
# Finally, define tests if we use libtap
if test "$enable_libtap" = "yes" ; then
AC_CONFIG_SUBDIRS([tap])
USE_LIBTAP=yes
else
USE_LIBTAP=no
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)
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)
perl subst include/locations.h
perl subst html/config.inc.php
echo ""
echo "Creating sample config files in sample-config/ ..."
perl subst sample-config/nagios.cfg
perl subst sample-config/cgi.cfg
perl subst sample-config/resource.cfg
perl subst sample-config/httpd.conf
perl subst sample-config/mrtg.cfg
perl subst sample-config/template-object/templates.cfg
perl subst sample-config/template-object/commands.cfg
perl subst sample-config/template-object/timeperiods.cfg
perl subst sample-config/template-object/contacts.cfg
perl subst sample-config/template-object/localhost.cfg
perl subst sample-config/template-object/windows.cfg
perl subst sample-config/template-object/printer.cfg
perl subst sample-config/template-object/switch.cfg
dnl Review options
echo ""
echo ""
AC_MSG_RESULT([*** Configuration summary for $PKG_NAME $PKG_VERSION $PKG_REL_DATE ***:])
echo ""
echo " General Options:"
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])
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])
echo ""
echo " Web Interface Options:"
echo " ------------------------"
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 ""
nagios/contrib/ 0000775 0000000 0000000 00000000000 12210155146 0013773 5 ustar 00root root 0000000 0000000 nagios/contrib/.gitignore 0000664 0000000 0000000 00000000023 12210155146 0015756 0 ustar 00root root 0000000 0000000 perlxsi.c
Makefile
nagios/contrib/Makefile.in 0000664 0000000 0000000 00000005001 12210155146 0016034 0 ustar 00root root 0000000 0000000 ###############################
# Makefile for contrib software
#
# Last Modified: 05-19-2008
###############################
CC=@CC@
CFLAGS=@CFLAGS@ @DEFS@
LDFLAGS=@LDFLAGS@ @LIBS@
# Source code directories
SRC_INCLUDE=../include
SRC_COMMON=../common
SRC_CGI=../cgi
# Generated automatically from configure script
SNPRINTF_O=@SNPRINTF_O@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
prefix=@prefix@
exec_prefix=@exec_prefix@
CGIDIR=@sbindir@
BINDIR=@bindir@
CGIS=traceroute.cgi daemonchk.cgi
UTILS=mini_epn new_mini_epn convertcfg
ALL=$(CGIS) $(UTILS)
CGI_C=$(SRC_CGI)/getcgi.c
CGI_O=$(SRC_CGI)/getcgi.o $(SNPRINTF_O)
CGI_H=$(SRC_INCLUDE)/getcgi.h
COMMON_H=$(SRC_INCLUDE)/config.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/locations.h
##############################################################################
# standard targets (all, clean, distclean, devclean, install)
all: $(ALL)
clean:
rm -f convertcfg daemonchk.cgi mini_epn new_mini_epn core *.o
rm -f */*/*~
rm -f */*~
rm -f *~
distclean: clean
rm -f Makefile
devclean: distclean
install:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CGIDIR)
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(BINDIR)
for f in $(CGIS); do $(INSTALL) -m 775 $(INSTALL_OPTS) $$f $(DESTDIR)$(CGIDIR); done
for f in $(UTILS); do $(INSTALL) -m 775 $(INSTALL_OPTS) $$f $(DESTDIR)$(BINDIR); done
##############################################################################
# rules and dependencies for actual target programs
daemonchk.cgi: daemonchk.o $(CGI_O) $(CGI_H) $(COMMON_H)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(CGI_O)
daemonchk.o: daemonchk.c
$(CC) $(CLFAGS) -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 $@
##############################################################################
# dependencies
$(CGI_O): $(CGI_C)
cd $(SRC_CGI) && make $(CGI_O)
##############################################################################
# implicit rules
%.cgi : %.c
$(CC) $(CFLAGS) $(LDFLAGS) $< $(CGI_O) -o $@
nagios/contrib/README 0000664 0000000 0000000 00000002443 12210155146 0014656 0 ustar 00root root 0000000 0000000 #####################
Nagios Contrib README
#####################
This directory contains various programs, scripts, etc. that
have been contribed by various people. Read the source code
if you want to find who did what.
Here is a description of what you'll find...
Conversion Programs:
--------------------
- convertcfg.c is a program to quickly convert old "host" config
files to the new template-based object config files. It can also
convert extended host information definitions. Type 'make convertcfg'
to compile the utility.
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
and place it in the CGI directory (i.e. /usr/local/nagios/sbin).
Requires Perl.
- daemonchk.c is a CGI contributed by Karl DeBisschop that can test to
see whether or not the Nagios process is running.
Miscellaneous Goodies:
----------------------
- htaccess.sample is a *sample* .htaccess file that can be used with
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.
nagios/contrib/convertcfg.c 0000664 0000000 0000000 00000055303 12210155146 0016305 0 ustar 00root root 0000000 0000000 /************************************************************************
*
* CONVERTCFG.C - Config File Convertor
*
* Copyright (c) 2001-2005 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 08-12-2005
*
* 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
char *my_strsep(char **, const char *);
int main(int argc, char **argv) {
FILE *fp;
char *temp_ptr;
char *temp_ptr2;
char input[8096];
int notify_recovery;
int notify_warning;
int notify_critical;
int notify_down;
int notify_unreachable;
int option;
int have_template = 0;
int x = 0, y = 0;
char *host_name;
char *service_description;
char *host_name2;
char *service_description2;
if(argc != 3) {
printf("Nagios Config File Converter\n");
printf("Written by Ethan Galstad (egalstad@nagios.org)\n");
printf("Last Modified: 08-12-2005\n");
printf("\n");
printf("Usage: %s