From adaf6ca0d9427cb6f0497440335e7289248d20f7 Mon Sep 17 00:00:00 2001 From: octo Date: Tue, 11 Apr 2006 17:22:25 +0000 Subject: [PATCH] A first version of the iokit-plugin. In need of a better name. --- configure.in | 22 +++++ src/Makefile.am | 11 +++ src/iokit.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 src/iokit.c diff --git a/configure.in b/configure.in index 77f3c83c..5b620250 100644 --- a/configure.in +++ b/configure.in @@ -157,6 +157,11 @@ AC_CHECK_HEADERS(mach/kern_return.h) # For hddtemp module AC_CHECK_HEADERS(linux/major.h) +# For the iokit module +AC_CHECK_HEADERS(CoreFoundation/CoreFoundation.h) +AC_CHECK_HEADERS(IOKit/IOKitLib.h) +AC_CHECK_HEADERS(IOKit/IOTypes.h) + # For load module AC_CHECK_HEADERS(sys/loadavg.h) @@ -546,6 +551,20 @@ AC_DEFINE_UNQUOTED(HAVE_LIBCURL, [$with_libcurl_numeric], [Define to 1 if you ha AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes") ### END of check for libcurl ### +with_libiokit="no" +collectd_libiokit=0 +AC_CHECK_LIB(IOKit, IOServiceGetMatchingServices, +[ + with_libiokit="yes" + collectd_libiokit=1 +], +[ + with_libiokit="no" + collectd_libiokit=0 +]) +AC_DEFINE_UNQUOTED(COLLECT_LIBIOKIT, [$collect_libiokit], [Wether or not to use the IOKit library]) +AM_CONDITIONAL(BUILD_WITH_LIBIOKIT, test "x$with_libiokit" = "xyes") + AC_ARG_WITH(libstatgrab, [AS_HELP_STRING([--with-libstatgrab@<:@=PREFIX@:>@], [Path to libstatgrab.])], [ if test "x$withval" != "xno" -a "x$withval" != "xyes" @@ -777,6 +796,7 @@ AC_COLLECTD([disk], [disable], [module], [disk/partition statistics]) AC_COLLECTD([df], [disable], [module], [df statistics]) AC_COLLECTD([quota], [enable], [module], [quota statistics (experimental)]) AC_COLLECTD([hddtemp], [disable], [module], [hdd temperature statistics]) +AC_COLLECTD([iokit], [disable], [module], [Apple's iokit hardware sensors]) AC_COLLECTD([load], [disable], [module], [system load statistics]) AC_COLLECTD([memory], [disable], [module], [memory statistics]) AC_COLLECTD([mysql], [disable], [module], [mysql statistics]) @@ -1015,6 +1035,7 @@ cat < + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" +#include "utils_debug.h" + +#define MODULE_NAME "iokit" + +#if HAVE_MACH_MACH_TYPES_H +# include +#endif +#if HAVE_MACH_MACH_INIT_H +# include +#endif +#if HAVE_MACH_MACH_ERROR_H +# include +#endif +#if HAVE_COREFOUNDATION_COREFOUNDATION_H +# include +#endif +#if HAVE_IOKIT_IOKITLIB_H +# include +#endif +#if HAVE_IOKIT_IOTYPES_H +# include +#endif + +#if HAVE_IOKIT_IOKITLIB_H +# define IOKIT_HAVE_READ 1 +#else +# define IOKIT_HAVE_READ 0 +#endif + +#if IOKIT_HAVE_READ +static mach_port_t io_master_port; +#endif + +static char *temperature_file = "temperature-%s.rrd"; + +static char *ds_def[] = +{ + "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U", + NULL +}; +static int ds_num = 1; + +static void iokit_init (void) +{ +#if IOKIT_HAVE_READ + kern_return_t status; + + /* FIXME: de-allocate port if it's defined */ + + status = IOMasterPort (MACH_PORT_NULL, &io_master_port); + if (status != kIOReturnSuccess) + { + syslog (LOG_ERR, "IOMasterPort failed: %s", + mach_error_string (status)); + io_master_port = MACH_PORT_NULL; + return; + } +#endif + + return; +} + +static void temperature_write (char *host, char *inst, char *val) +{ + rrd_update_file (host, temperature_file, val, ds_def, ds_num); +} + +#if IOKIT_HAVE_READ +static void iokit_submit (char *type, char *inst, int value) +{ + char buf[128]; + + if (snprintf (buf, 1024, "%u:%i", (unsigned int) curtime, + value) >= 128) + return; + + plugin_submit (type, inst, buf); +} + +static void iokit_read (void) +{ + kern_return_t status; + io_iterator_t iterator; + io_object_t io_obj; + CFMutableDictionaryRef prop_dict; + CFTypeRef property; + + char type[128]; + char inst[128]; + int value; + + if (!io_master_port || (io_master_port == MACH_PORT_NULL)) + return; + + status = IOServiceGetMatchingServices (io_master_port, + IOServiceNameMatching("IOHWSensor"), + &iterator); + if (status != kIOReturnSuccess) + { + syslog (LOG_ERR, "IOServiceGetMatchingServices failed: %s", + mach_error_string (status)); + return; + } + + while ((io_obj = IOIteratorNext (iterator))) + { + prop_dict = NULL; + status = IORegistryEntryCreateCFProperties (io_obj, + &prop_dict, + kCFAllocatorDefault, + kNilOptions); + if (status != kIOReturnSuccess) + { + DBG ("IORegistryEntryCreateCFProperties failed: %s", + mach_error_string (status)); + continue; + } + + /* Copy the sensor type. */ + property = NULL; + if (!CFDictionaryGetValueIfPresent (prop_dict, + CFSTR ("type"), + &property)) + continue; + if (CFGetTypeID (property) != CFStringGetTypeID ()) + continue; + if (!CFStringGetCString (property, + type, 128, + kCFStringEncodingASCII)) + continue; + type[127] = '\0'; + + /* Copy the sensor location. This will be used as `instance'. */ + property = NULL; + if (!CFDictionaryGetValueIfPresent (prop_dict, + CFSTR ("location"), + &property)) + continue; + if (CFGetTypeID (property) != CFStringGetTypeID ()) + continue; + if (!CFStringGetCString (property, + inst, 128, + kCFStringEncodingASCII)) + continue; + inst[127] = '\0'; + + /* Get the actual value. Some computation, based on the `type' + * is neccessary. */ + property = NULL; + if (!CFDictionaryGetValueIfPresent (prop_dict, + CFSTR ("current-value"), + &property)) + continue; + if (CFGetTypeID (property) != CFNumberGetTypeID ()) + continue; + if (!CFNumberGetValue (property, + kCFNumberIntType, + &value)) + continue; + + /* Do stuff */ + DBG ("type = %s, inst = %s, value = %i", + type, inst, value); + iokit_submit (type, inst, value); + + CFRelease (prop_dict); + IOObjectRelease (io_obj); + } /* while (iterator) */ + + IOObjectRelease (iterator); +} +#else +# define iokit_read NULL +#endif /* IOKIT_HAVE_READ */ + +void module_register (void) +{ + DBG ("IOKIT_HAVE_READ = %i", IOKIT_HAVE_READ); + + plugin_register (MODULE_NAME, iokit_init, iokit_read, NULL); + plugin_register ("iokit-temperature", NULL, NULL, temperature_write); +} + +#undef MODULE_NAME -- 2.30.2