Merge branch 'master' into collectd-4
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Thu, 15 Mar 2007 17:33:12 +0000 (18:33 +0100)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Thu, 15 Mar 2007 17:33:12 +0000 (18:33 +0100)
Conflicts:

configure.in

86 files changed:
configure.in
src/Makefile.am
src/apache.c
src/apcups.c
src/apple_sensors.c
src/battery.c
src/collectd-nagios.c [new file with mode: 0644]
src/collectd.c
src/collectd.conf.in
src/collectd.conf.pod
src/collectd.h
src/common.c
src/common.h
src/configfile.c
src/configfile.h
src/cpu.c
src/cpufreq.c
src/csv.c [new file with mode: 0644]
src/df.c
src/disk.c
src/dns.c
src/email.c
src/entropy.c [new file with mode: 0644]
src/exec.c [new file with mode: 0644]
src/hddtemp.c
src/irq.c
src/libconfig/AUTHORS [deleted file]
src/libconfig/LICENSE [deleted file]
src/libconfig/Makefile.am [deleted file]
src/libconfig/README [deleted file]
src/libconfig/TODO [deleted file]
src/libconfig/compat.h [deleted file]
src/libconfig/conf_apache.c [deleted file]
src/libconfig/conf_apache.h [deleted file]
src/libconfig/conf_colon.c [deleted file]
src/libconfig/conf_colon.h [deleted file]
src/libconfig/conf_equal.c [deleted file]
src/libconfig/conf_equal.h [deleted file]
src/libconfig/conf_section.c [deleted file]
src/libconfig/conf_section.h [deleted file]
src/libconfig/conf_space.c [deleted file]
src/libconfig/conf_space.h [deleted file]
src/libconfig/conf_xml.c [deleted file]
src/libconfig/conf_xml.h [deleted file]
src/libconfig/libconfig.c [deleted file]
src/libconfig/libconfig.h [deleted file]
src/libconfig/libconfig_private.h [deleted file]
src/libconfig/test-lc.c [deleted file]
src/libconfig/win32.h [deleted file]
src/liboconfig/AUTHORS [new file with mode: 0644]
src/liboconfig/COPYING [new file with mode: 0644]
src/liboconfig/ChangeLog [new file with mode: 0644]
src/liboconfig/Makefile.am [new file with mode: 0644]
src/liboconfig/aux_types.h [new file with mode: 0644]
src/liboconfig/oconfig.c [new file with mode: 0644]
src/liboconfig/oconfig.h [new file with mode: 0644]
src/liboconfig/parser.y [new file with mode: 0644]
src/liboconfig/scanner.l [new file with mode: 0644]
src/load.c
src/mbmon.c
src/memory.c
src/multimeter.c
src/mysql.c
src/network.c
src/network.h
src/nfs.c
src/ntpd.c
src/ping.c
src/plugin.c
src/plugin.h
src/processes.c
src/rrdtool.c [new file with mode: 0644]
src/sensors.c
src/serial.c
src/swap.c
src/syslog.c [new file with mode: 0644]
src/tape.c
src/traffic.c
src/unixsock.c [new file with mode: 0644]
src/users.c
src/utils_avltree.c [new file with mode: 0644]
src/utils_avltree.h [new file with mode: 0644]
src/utils_llist.c [new file with mode: 0644]
src/utils_llist.h [new file with mode: 0644]
src/vserver.c
src/wireless.c

index 7251383..ff12f68 100644 (file)
@@ -24,7 +24,8 @@ AC_SUBST(LTDLINCL)
 AC_SUBST(LIBLTDL)
 AC_LIBTOOL_DLOPEN
 AC_PROG_LIBTOOL
-#AC_PROG_RANLIB
+AC_PROG_LEX
+AC_PROG_YACC
 AC_CONFIG_SUBDIRS(libltdl)
 
 #
@@ -44,7 +45,7 @@ AC_CHECK_HEADERS(assert.h)
 AC_CHECK_HEADERS(sys/types.h)
 AC_CHECK_HEADERS(sys/socket.h)
 AC_CHECK_HEADERS(sys/select.h)
-AC_CHECK_HEADERS(sys/poll.h)
+AC_CHECK_HEADERS(poll.h)
 AC_CHECK_HEADERS(netdb.h)
 AC_CHECK_HEADERS(arpa/inet.h)
 AC_CHECK_HEADERS(sys/resource.h)
@@ -149,6 +150,23 @@ AC_CHECK_HEADERS(netinet/icmp6.h, [], [],
 # include <netinet/ip6.h>
 #endif
 ])
+AC_CHECK_HEADERS(netinet/tcp.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+])
 AC_CHECK_HEADERS(netinet/udp.h, [], [],
 [#if HAVE_STDINT_H
 # include <stdint.h>
@@ -309,6 +327,10 @@ AC_CHECK_HEADERS(net/if_arp.h)
 AC_CHECK_HEADERS(net/if_ppp.h)
 AC_CHECK_HEADERS(netinet/if_ether.h)
 
+# For the multimeter plugin
+AC_CHECK_HEADERS(termios.h)
+AC_CHECK_HEADERS(sys/ioctl.h)
+
 #
 # Checking for libraries
 #
@@ -366,6 +388,98 @@ AC_CHECK_FUNCS(getgrgid getpwuid)
 # For traffic module
 AC_CHECK_FUNCS(getifaddrs)
 
+# Check for NAN
+nan_type="none"
+if test "x$nan_type" = "xnone"; then
+  AC_CACHE_CHECK([whether NAN is defined by default],
+    [have_nan_default],
+    AC_COMPILE_IFELSE(
+      AC_LANG_PROGRAM(
+      [[
+#include <stdlib.h>
+#include <math.h>
+static float foo = NAN;
+      ]],
+      [[
+       if (isnan (foo))
+        return 0;
+       else
+       return 1;
+      ]]),
+      [have_nan_default="yes"],
+      [have_nan_default="no"]
+    )
+  )
+  if test "x$have_nan_default" = "xyes"
+  then
+   nan_type="default"
+   AC_DEFINE(NAN_STATIC_DEFAULT, 1,
+     [Define if NAN is defined by default and can initialize static variables.])
+  fi
+fi
+if test "x$nan_type" = "xnone"; then
+  AC_CACHE_CHECK([whether NAN is defined by __USE_ISOC99],
+    [have_nan_isoc],
+    AC_COMPILE_IFELSE(
+      AC_LANG_PROGRAM(
+      [[
+#include <stdlib.h>
+#define __USE_ISOC99 1
+#include <math.h>
+static float foo = NAN;
+      ]],
+      [[
+       if (isnan (foo))
+        return 0;
+       else
+       return 1;
+      ]]),
+      [have_nan_isoc="yes"],
+      [have_nan_isoc="no"]
+    )
+  )
+  if test "x$have_nan_isoc" = "xyes"
+  then
+   nan_type="isoc99"
+   AC_DEFINE(NAN_STATIC_ISOC, 1,
+     [Define if NAN is defined by __USE_ISOC99 and can initialize static variables.])
+  fi
+fi
+if test "x$nan_type" = "xnone"; then
+  AC_CACHE_CHECK([whether NAN can be defined by 0/0],
+    [have_nan_zero],
+    AC_RUN_IFELSE(
+      AC_LANG_PROGRAM(
+      [[
+#include <stdlib.h>
+#include <math.h>
+#define NAN (0.0 / 0.0)
+#ifndef isnan
+# define isnan(f) ((f) != (f))
+#endif
+static float foo = NAN;
+      ]],
+      [[
+       if (isnan (foo))
+        return 0;
+       else
+       return 1;
+      ]]),
+      [have_nan_zero="yes"],
+      [have_nan_zero="no"]
+    )
+  )
+  if test "x$have_nan_zero" = "xyes"
+  then
+   nan_type="zero"
+   AC_DEFINE(NAN_ZERO_ZERO, 1,
+     [Define if NAN can be defined as (0.0 / 0.0)])
+  fi
+fi
+if test "x$nan_type" = "xnone"; then
+  AC_MSG_ERROR([Didn't find out how to statically initialize variables to NAN. Sorry.])
+fi
+
 # For mount interface
 #AC_CHECK_FUNCS(getfsent getvfsent)
 
@@ -1082,10 +1196,12 @@ AC_COLLECTD([battery],   [disable], [module], [battery statistics])
 AC_COLLECTD([cpu],       [disable], [module], [cpu usage statistics])
 AC_COLLECTD([cpufreq],   [disable], [module], [system cpu frequency statistics])
 AC_COLLECTD([disk],      [disable], [module], [disk/partition statistics])
+AC_COLLECTD([csv],       [disable], [module], [csv output plugin])
 AC_COLLECTD([df],        [disable], [module], [df statistics])
 AC_COLLECTD([dns],       [disable], [module], [dns statistics])
 AC_COLLECTD([email],     [disable], [module], [email statistics])
-AC_COLLECTD([quota],     [enable],  [module], [quota statistics (experimental)])
+AC_COLLECTD([entropy],   [disable], [module], [entropy statistics])
+AC_COLLECTD([exec],      [disable], [module], [exec of external programs])
 AC_COLLECTD([hddtemp],   [disable], [module], [hdd temperature statistics])
 AC_COLLECTD([iptables],  [disable], [module], [IPtables statistics])
 AC_COLLECTD([irq],       [disable], [module], [irq statistics])
@@ -1094,6 +1210,7 @@ AC_COLLECTD([mbmon],     [disable], [module], [motherboard monitor statistics])
 AC_COLLECTD([memory],    [disable], [module], [memory statistics])
 AC_COLLECTD([multimeter],[disable], [module], [multimeter statistics])
 AC_COLLECTD([mysql],     [disable], [module], [mysql statistics])
+AC_COLLECTD([network],   [disable], [module], [network functionality])
 AC_COLLECTD([nfs],       [disable], [module], [nfs statistics])
 AC_COLLECTD([ntpd],      [disable], [module], [ntpd statistics])
 AC_COLLECTD([ping],      [disable], [module], [ping statistics])
@@ -1101,13 +1218,15 @@ AC_COLLECTD([processes], [disable], [module], [processes statistics])
 AC_COLLECTD([sensors],   [disable], [module], [lm_sensors statistics])
 AC_COLLECTD([serial],    [disable], [module], [serial statistics])
 AC_COLLECTD([swap],      [disable], [module], [swap statistics])
+AC_COLLECTD([syslog],    [disable], [module], [syslog log facility])
 AC_COLLECTD([tape],      [disable], [module], [tape statistics])
 AC_COLLECTD([traffic],   [disable], [module], [system traffic statistics])
+AC_COLLECTD([unixsock],  [disable], [module], [UNIX socket plugin])
 AC_COLLECTD([users],     [disable], [module], [user count statistics])
 AC_COLLECTD([vserver],   [disable], [module], [vserver statistics])
 AC_COLLECTD([wireless],  [disable], [module], [wireless link statistics])
 
-AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/libconfig/Makefile src/liboping/Makefile)
+AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/liboconfig/Makefile src/liboping/Makefile)
 
 cat <<EOF;
 
@@ -1138,10 +1257,13 @@ Configuration:
     battery . . . . . . $enable_battery
     cpu . . . . . . . . $enable_cpu
     cpufreq . . . . . . $enable_cpufreq
+    csv . . . . . . . . $enable_csv
     df  . . . . . . . . $enable_df
     disk  . . . . . . . $enable_disk
     dns . . . . . . . . $enable_dns
     email . . . . . . . $enable_email
+    entropy . . . . . . $enable_entropy
+    exec  . . . . . . . $enable_exec
     hddtemp . . . . . . $enable_hddtemp
     irq . . . . . . . . $enable_irq
     iptables  . . . . . $enable_iptables
@@ -1150,6 +1272,7 @@ Configuration:
     memory  . . . . . . $enable_memory
     multimeter  . . . . $enable_multimeter
     mysql . . . . . . . $enable_mysql
+    network . . . . . . $enable_network
     nfs . . . . . . . . $enable_nfs
     ntpd  . . . . . . . $enable_ntpd
     ping  . . . . . . . $enable_ping
@@ -1157,8 +1280,10 @@ Configuration:
     sensors . . . . . . $enable_sensors
     serial  . . . . . . $enable_serial
     swap  . . . . . . . $enable_swap
+    syslog  . . . . . . $enable_syslog
     tape  . . . . . . . $enable_tape
     traffic . . . . . . $enable_traffic
+    unixsock  . . . . . $enable_unixsock
     users . . . . . . . $enable_users
     vserver . . . . . . $enable_vserver
     wireless  . . . . . $enable_wireless
index aee7479..0610aa6 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = libconfig
+SUBDIRS = liboconfig
 if BUILD_WITH_OWN_LIBOPING
 SUBDIRS += liboping
 endif
@@ -8,16 +8,19 @@ AM_CFLAGS = -Wall -Werror
 endif
 
 sbin_PROGRAMS = collectd
+bin_PROGRAMS = collectd-nagios
 
 collectd_SOURCES = collectd.c collectd.h \
                   utils_debug.c utils_debug.h \
+                  utils_avltree.c utils_avltree.h \
                   utils_mount.c utils_mount.h \
+                  utils_llist.c utils_llist.h \
                   utils_ignorelist.c utils_ignorelist.h \
                   common.c common.h \
-                  network.c network.h \
                   plugin.c plugin.h \
                   configfile.c configfile.h
 collectd_CPPFLAGS = $(LTDLINCL)
+collectd_CPPFLAGS += -DPREFIX='"${prefix}"'
 collectd_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
 collectd_CPPFLAGS += -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"'
 if BUILD_FEATURE_DAEMON
@@ -30,9 +33,6 @@ endif
 
 # Link to these libraries..
 collectd_LDFLAGS = -export-dynamic
-if BUILD_WITH_RRDTOOL
-collectd_LDFLAGS += -lm -lrrd
-endif
 if BUILD_WITH_LIBRT
 collectd_LDFLAGS += -lrt
 endif
@@ -60,8 +60,10 @@ collectd_LDFLAGS += -lstatgrab
 endif
 
 
-collectd_LDADD = $(LIBLTDL) libconfig/libconfig.la "-dlopen" self
-collectd_DEPENDENCIES = $(LIBLTDL) libconfig/libconfig.la
+collectd_LDADD = $(LIBLTDL) liboconfig/liboconfig.la "-dlopen" self
+collectd_DEPENDENCIES = $(LIBLTDL) liboconfig/liboconfig.la
+
+collectd_nagios_SOURCES = collectd-nagios.c
 
 pkglib_LTLIBRARIES = 
 
@@ -131,6 +133,14 @@ collectd_LDADD += "-dlopen" cpufreq.la
 collectd_DEPENDENCIES += cpufreq.la
 endif
 
+if BUILD_MODULE_CSV
+pkglib_LTLIBRARIES += csv.la
+csv_la_SOURCES = csv.c
+csv_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" csv.la
+collectd_DEPENDENCIES += csv.la
+endif
+
 if BUILD_MODULE_DF
 pkglib_LTLIBRARIES += df.la
 df_la_SOURCES = df.c
@@ -186,6 +196,25 @@ collectd_LDADD += "-dlopen" email.la
 collectd_DEPENDENCIES += email.la
 endif
 
+if BUILD_MODULE_ENTROPY
+pkglib_LTLIBRARIES += entropy.la
+entropy_la_SOURCES = entropy.c
+entropy_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" entropy.la
+collectd_DEPENDENCIES += entropy.la
+endif
+
+if BUILD_MODULE_EXEC
+pkglib_LTLIBRARIES += exec.la
+exec_la_SOURCES = exec.c
+exec_la_LDFLAGS = -module -avoid-version
+if BUILD_WITH_LIBPTHREAD
+exec_la_LDFLAGS += -lpthread
+endif
+collectd_LDADD += "-dlopen" exec.la
+collectd_DEPENDENCIES += exec.la
+endif
+
 #if BUILD_MODULE_QUOTA
 #pkglib_LTLIBRARIES += quota.la
 #quota_la_SOURCES = quota_plugin.c quota_plugin.h
@@ -297,6 +326,20 @@ collectd_LDADD += "-dlopen" mysql.la
 collectd_DEPENDENCIES += mysql.la
 endif
 
+if BUILD_MODULE_NETWORK
+pkglib_LTLIBRARIES += network.la
+network_la_SOURCES = network.c
+network_la_LDFLAGS = -module -avoid-version
+if BUILD_WITH_LIBSOCKET
+network_la_LDFLAGS += -lsocket
+endif
+if BUILD_WITH_LIBPTHREAD
+network_la_LDFLAGS += -lpthread
+endif
+collectd_LDADD += "-dlopen" network.la
+collectd_DEPENDENCIES += network.la
+endif
+
 if BUILD_MODULE_NFS
 pkglib_LTLIBRARIES += nfs.la
 nfs_la_SOURCES = nfs.c
@@ -340,6 +383,14 @@ collectd_LDADD += "-dlopen" processes.la
 collectd_DEPENDENCIES += processes.la
 endif
 
+if BUILD_WITH_RRDTOOL
+pkglib_LTLIBRARIES += rrdtool.la
+rrdtool_la_SOURCES = rrdtool.c
+rrdtool_la_LDFLAGS = -module -avoid-version -lrrd
+collectd_LDADD += "-dlopen" rrdtool.la
+collectd_DEPENDENCIES += rrdtool.la
+endif
+
 if BUILD_MODULE_SENSORS
 pkglib_LTLIBRARIES += sensors.la
 sensors_la_SOURCES = sensors.c
@@ -382,6 +433,14 @@ swap_la_LDFLAGS += -lstatgrab
 endif
 endif
 
+if BUILD_MODULE_SYSLOG
+pkglib_LTLIBRARIES += syslog.la
+syslog_la_SOURCES = syslog.c
+syslog_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" syslog.la
+collectd_DEPENDENCIES += syslog.la
+endif
+
 if BUILD_MODULE_TAPE
 pkglib_LTLIBRARIES += tape.la
 tape_la_SOURCES = tape.c
@@ -419,6 +478,17 @@ traffic_la_LDFLAGS += -lstatgrab
 endif
 endif
 
+if BUILD_MODULE_UNIXSOCK
+pkglib_LTLIBRARIES += unixsock.la
+unixsock_la_SOURCES = unixsock.c
+unixsock_la_LDFLAGS = -module -avoid-version
+if BUILD_WITH_LIBPTHREAD
+unixsock_la_LDFLAGS += -lpthread
+endif
+collectd_LDADD += "-dlopen" unixsock.la
+collectd_DEPENDENCIES += unixsock.la
+endif
+
 if BUILD_MODULE_USERS
 pkglib_LTLIBRARIES += users.la
 users_la_SOURCES = users.c
index 7c48f08..167ead1 100644 (file)
@@ -5,8 +5,7 @@
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,8 +26,7 @@
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
-
-#define MODULE_NAME "apache"
+#include "utils_debug.h"
 
 #if HAVE_LIBCURL && HAVE_CURL_CURL_H
 #  define APACHE_HAVE_READ 1
 #  define APACHE_HAVE_READ 0
 #endif
 
-static char *url    = NULL;
-static char *user   = NULL;
-static char *pass   = NULL;
-static char *cacert = NULL;
-
-#if HAVE_LIBCURL
-static CURL *curl = NULL;
-
-#define ABUFFER_SIZE 16384
-static char apache_buffer[ABUFFER_SIZE];
-static int  apache_buffer_len = 0;
-static char apache_curl_error[CURL_ERROR_SIZE];
-#endif /* HAVE_LIBCURL */
-
 /* Limit to 2^27 bytes/s. That's what a gigabit-ethernet link can handle, in
  * theory. */
-static char *bytes_file = "apache/apache_bytes.rrd";
-static char *bytes_ds_def[] =
+static data_source_t apache_bytes_dsrc[1] =
 {
-       "DS:count:COUNTER:"COLLECTD_HEARTBEAT":0:134217728",
-       NULL
+       {"count", DS_TYPE_COUNTER, 0, 134217728.0},
+};
+
+static data_set_t apache_bytes_ds =
+{
+       "apache_bytes", 1, apache_bytes_dsrc
 };
-static int bytes_ds_num = 1;
 
 /* Limit to 2^20 requests/s */
-static char *requests_file = "apache/apache_requests.rrd";
-static char *requests_ds_def[] =
+static data_source_t apache_requests_dsrc[1] =
 {
-       "DS:count:COUNTER:"COLLECTD_HEARTBEAT":0:1048576",
-       NULL
+       {"count", DS_TYPE_COUNTER, 0, 134217728.0},
 };
-static int requests_ds_num = 1;
 
-static char *scoreboard_file = "apache/apache_scoreboard-%s.rrd";
-static char *scoreboard_ds_def[] =
+static data_set_t apache_requests_ds =
 {
-       "DS:count:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       "apache_requests", 1, apache_requests_dsrc
 };
-static int scoreboard_ds_num = 1;
 
-/* for lighttpd; Limit to 65536 active connections */
-static char *connections_file = "apache/apache_connections.rrd";
-static char *connections_ds_def[] =
+static data_source_t apache_scoreboard_dsrc[1] =
 {
-       "DS:connections:GAUGE:"COLLECTD_HEARTBEAT":0:65536", 
-       NULL
+       {"count", DS_TYPE_GAUGE, 0, 65535.0},
+};
+
+static data_set_t apache_scoreboard_ds =
+{
+       "apache_scoreboard", 1, apache_scoreboard_dsrc
 };
-static int connections_ds_num = 1;
 
-static char *config_keys[] =
+static data_source_t apache_connections_dsrc[1] =
+{
+       {"count", DS_TYPE_GAUGE, 0, 65535.0},
+};
+
+static data_set_t apache_connections_ds =
+{
+       "apache_connections", 1, apache_connections_dsrc
+};
+
+#if APACHE_HAVE_READ
+static char *url    = NULL;
+static char *user   = NULL;
+static char *pass   = NULL;
+static char *cacert = NULL;
+
+static CURL *curl = NULL;
+
+#define ABUFFER_SIZE 16384
+static char apache_buffer[ABUFFER_SIZE];
+static int  apache_buffer_len = 0;
+static char apache_curl_error[CURL_ERROR_SIZE];
+
+static const char *config_keys[] =
 {
        "URL",
        "User",
@@ -97,7 +101,6 @@ static char *config_keys[] =
 };
 static int config_keys_num = 4;
 
-#if HAVE_LIBCURL
 static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb, void *stream)
 {
        size_t len = size * nmemb;
@@ -116,9 +119,8 @@ static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb, void *
 
        return (len);
 }
-#endif /* HAVE_LIBCURL */
 
-static int config_set (char **var, char *value)
+static int config_set (char **var, const char *value)
 {
        if (*var != NULL)
        {
@@ -132,7 +134,7 @@ static int config_set (char **var, char *value)
                return (0);
 }
 
-static int config (char *key, char *value)
+static int config (const char *key, const char *value)
 {
        if (strcasecmp (key, "url") == 0)
                return (config_set (&url, value));
@@ -146,9 +148,8 @@ static int config (char *key, char *value)
                return (-1);
 }
 
-static void init (void)
+static int init (void)
 {
-#if HAVE_LIBCURL
        static char credentials[1024];
 
        if (curl != NULL)
@@ -159,7 +160,7 @@ static void init (void)
        if ((curl = curl_easy_init ()) == NULL)
        {
                syslog (LOG_ERR, "apache: `curl_easy_init' failed.");
-               return;
+               return (-1);
        }
 
        curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, apache_curl_callback);
@@ -171,7 +172,7 @@ static void init (void)
                if (snprintf (credentials, 1024, "%s:%s", user, pass == NULL ? "" : pass) >= 1024)
                {
                        syslog (LOG_ERR, "apache: Credentials would have been truncated.");
-                       return;
+                       return (-1);
                }
 
                curl_easy_setopt (curl, CURLOPT_USERPWD, credentials);
@@ -186,55 +187,56 @@ static void init (void)
        {
                curl_easy_setopt (curl, CURLOPT_CAINFO, cacert);
        }
-#endif /* HAVE_LIBCURL */
-}
 
-static void bytes_write (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, bytes_file, val, bytes_ds_def, bytes_ds_num);
-}
+       return (0);
+} /* int init */
 
-static void requests_write (char *host, char *inst, char *val)
+static void submit_counter (const char *type, const char *type_instance,
+               unsigned long long value)
 {
-       rrd_update_file (host, requests_file, val, requests_ds_def, requests_ds_num);
-}
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-static void scoreboard_write (char *host, char *inst, char *val)
-{
-       char buf[1024];
+       DBG ("type = %s; type_instance = %s; value = %llu;",
+                       type, type_instance, value);
 
-       if (snprintf (buf, 1024, scoreboard_file, inst) >= 1024)
-               return;
+       values[0].counter = value;
 
-       rrd_update_file (host, buf, val, scoreboard_ds_def, scoreboard_ds_num);
-}
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "apache");
+       strcpy (vl.plugin_instance, "");
+       strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
-static void connections_write (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, connections_file, val, connections_ds_def,
-                       connections_ds_num);
-}
+       plugin_dispatch_values (type, &vl);
+} /* void submit_counter */
 
-#if APACHE_HAVE_READ
-static void submit (char *type, char *inst, long long value)
+static void submit_gauge (const char *type, const char *type_instance,
+               double value)
 {
-       char buf[1024];
-       int  status;
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       status = snprintf (buf, 1024, "%u:%lli", (unsigned int) curtime, value);
-       if (status < 0)
-       {
-               syslog (LOG_ERR, "apache: bytes_submit: snprintf failed");
-               return;
-       }
-       else if (status >= 1024)
-       {
-               syslog (LOG_WARNING, "apache: bytes_submit: snprintf was truncated");
-               return;
-       }
+       DBG ("type = %s; type_instance = %s; value = %lf;",
+                       type, type_instance, value);
 
-       plugin_submit (type, inst, buf);
-}
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "apache");
+       strcpy (vl.plugin_instance, "");
+
+       if (type_instance != NULL)
+               strncpy (vl.type_instance, type_instance,
+                               sizeof (vl.type_instance));
+
+       plugin_dispatch_values (type, &vl);
+} /* void submit_counter */
 
 static void submit_scoreboard (char *buf)
 {
@@ -274,24 +276,25 @@ static void submit_scoreboard (char *buf)
                else if (buf[i] == 'I') idle_cleanup++;
        }
 
-       submit ("apache_scoreboard", "open"     , open);
-       submit ("apache_scoreboard", "waiting"  , waiting);
-       submit ("apache_scoreboard", "starting" , starting);
-       submit ("apache_scoreboard", "reading"  , reading);
-       submit ("apache_scoreboard", "sending"  , sending);
-       submit ("apache_scoreboard", "keepalive", keepalive);
-       submit ("apache_scoreboard", "dnslookup", dnslookup);
-       submit ("apache_scoreboard", "closing"  , closing);
-       submit ("apache_scoreboard", "logging"  , logging);
-       submit ("apache_scoreboard", "finishing", finishing);
-       submit ("apache_scoreboard", "idle_cleanup", idle_cleanup);
+       submit_gauge ("apache_scoreboard", "open"     , open);
+       submit_gauge ("apache_scoreboard", "waiting"  , waiting);
+       submit_gauge ("apache_scoreboard", "starting" , starting);
+       submit_gauge ("apache_scoreboard", "reading"  , reading);
+       submit_gauge ("apache_scoreboard", "sending"  , sending);
+       submit_gauge ("apache_scoreboard", "keepalive", keepalive);
+       submit_gauge ("apache_scoreboard", "dnslookup", dnslookup);
+       submit_gauge ("apache_scoreboard", "closing"  , closing);
+       submit_gauge ("apache_scoreboard", "logging"  , logging);
+       submit_gauge ("apache_scoreboard", "finishing", finishing);
+       submit_gauge ("apache_scoreboard", "idle_cleanup", idle_cleanup);
 }
 
-static void apache_read (void)
+static int apache_read (void)
 {
        int i;
 
        char *ptr;
+       char *saveptr;
        char *lines[16];
        int   lines_num = 0;
 
@@ -299,19 +302,21 @@ static void apache_read (void)
        int   fields_num;
 
        if (curl == NULL)
-               return;
+               return (-1);
        if (url == NULL)
-               return;
+               return (-1);
 
        apache_buffer_len = 0;
        if (curl_easy_perform (curl) != 0)
        {
-               syslog (LOG_WARNING, "apache: curl_easy_perform failed: %s", apache_curl_error);
-               return;
+               syslog (LOG_ERR, "apache: curl_easy_perform failed: %s",
+                               apache_curl_error);
+               return (-1);
        }
 
        ptr = apache_buffer;
-       while ((lines[lines_num] = strtok (ptr, "\n\r")) != NULL)
+       saveptr = NULL;
+       while ((lines[lines_num] = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
        {
                ptr = NULL;
                lines_num++;
@@ -328,34 +333,39 @@ static void apache_read (void)
                {
                        if ((strcmp (fields[0], "Total") == 0)
                                        && (strcmp (fields[1], "Accesses:") == 0))
-                               submit ("apache_requests", NULL, atoll (fields[2]));
+                               submit_counter ("apache_requests", "",
+                                               atoll (fields[2]));
                        else if ((strcmp (fields[0], "Total") == 0)
                                        && (strcmp (fields[1], "kBytes:") == 0))
-                               submit ("apache_bytes", NULL, 1024LL * atoll (fields[2]));
+                               submit_counter ("apache_bytes", "",
+                                               1024LL * atoll (fields[2]));
                }
                else if (fields_num == 2)
                {
                        if (strcmp (fields[0], "Scoreboard:") == 0)
                                submit_scoreboard (fields[1]);
                        else if (strcmp (fields[0], "BusyServers:") == 0)
-                               submit ("apache_connections", NULL, atol (fields[1]));
+                               submit_gauge ("apache_connections", NULL, atol (fields[1]));
                }
        }
 
        apache_buffer_len = 0;
-}
-#else
-#  define apache_read NULL
+
+       return (0);
+} /* int apache_read */
 #endif /* APACHE_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, init, apache_read, NULL);
-       plugin_register ("apache_requests",   NULL, NULL, requests_write);
-       plugin_register ("apache_bytes",      NULL, NULL, bytes_write);
-       plugin_register ("apache_scoreboard", NULL, NULL, scoreboard_write);
-       plugin_register ("apache_connections", NULL, NULL, connections_write);
-       cf_register (MODULE_NAME, config, config_keys, config_keys_num);
-}
+       plugin_register_data_set (&apache_bytes_ds);
+       plugin_register_data_set (&apache_requests_ds);
+       plugin_register_data_set (&apache_scoreboard_ds);
+       plugin_register_data_set (&apache_connections_ds);
 
-#undef MODULE_NAME
+#if APACHE_HAVE_READ
+       plugin_register_config ("apache", config,
+                       config_keys, config_keys_num);
+       plugin_register_init ("apache", init);
+       plugin_register_read ("apache", apache_read);
+#endif
+}
index cd64426..9fab785 100644 (file)
 # include <netinet/in.h>
 #endif
 
-#ifndef APCMAIN
-# define APCMAIN 0
-#endif
-
 #define NISPORT 3551
 #define MAXSTRING               256
 #define MODULE_NAME "apcups"
 
 #define APCUPS_DEFAULT_HOST "localhost"
 
+/*
+ * Private data types
+ */
+struct apc_detail_s
+{
+       double linev;
+       double loadpct;
+       double bcharge;
+       double timeleft;
+       double outputv;
+       double itemp;
+       double battv;
+       double linefreq;
+};
+
+/*
+ * Private variables
+ */
 /* Default values for contacting daemon */
-static char *global_host = NULL;
-static int   global_port = NISPORT;
+static char *conf_host = NULL;
+static int   conf_port = NISPORT;
+
+static int global_sockfd = -1;
 
 /* 
  * The following are only if not compiled to test the module with its own main.
 */
-#if !APCMAIN
-static char *bvolt_file_template = "apcups/voltage-%s.rrd";
-static char *bvolt_ds_def[] = 
+static data_source_t data_source_voltage[1] =
 {
-       "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+       {"value", DS_TYPE_GAUGE, NAN, NAN}
 };
-static int bvolt_ds_num = 1;
 
-static char *load_file_template = "apcups/load_percent.rrd";
-static char *load_ds_def[] = 
+static data_set_t ds_voltage =
 {
-       "DS:percent:GAUGE:"COLLECTD_HEARTBEAT":0:110",
+       "voltage", 1, data_source_voltage
 };
-static int load_ds_num = 1;
 
-static char *charge_file_template = "apcups/charge_percent.rrd";
-static char *charge_ds_def[] = 
+static data_source_t data_source_percent[1] =
 {
-       "DS:percent:GAUGE:"COLLECTD_HEARTBEAT":0:110",
+       {"percent", DS_TYPE_GAUGE, 0, 100.1}
 };
-static int charge_ds_num = 1;
 
-static char *time_file_template = "apcups/timeleft.rrd";
-static char *time_ds_def[] = 
+static data_set_t ds_percent =
 {
-       "DS:timeleft:GAUGE:"COLLECTD_HEARTBEAT":0:100",
+       "percent", 1, data_source_percent
 };
-static int time_ds_num = 1;
 
-static char *temp_file_template = "apcups/temperature.rrd";
-static char *temp_ds_def[] = 
+static data_source_t data_source_timeleft[1] =
 {
-       /* -273.15 is absolute zero */
-       "DS:value:GAUGE:"COLLECTD_HEARTBEAT":-274:U",
+       {"timeleft", DS_TYPE_GAUGE, 0, 100.0}
 };
-static int temp_ds_num = 1;
 
-static char *freq_file_template = "apcups/frequency-%s.rrd";
-static char *freq_ds_def[] = 
+static data_set_t ds_timeleft =
 {
-       "DS:frequency:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+       "timeleft", 1, data_source_timeleft
 };
-static int freq_ds_num = 1;
 
-static char *config_keys[] =
+static data_source_t data_source_temperature[1] =
 {
-       "Host",
-       "Port",
-       NULL
+       {"value", DS_TYPE_GAUGE, -273.15, NAN}
 };
-static int config_keys_num = 2;
 
-#endif /* if APCMAIN */
+static data_set_t ds_temperature =
+{
+       "temperature", 1, data_source_temperature
+};
 
-struct apc_detail_s
+static data_source_t data_source_frequency[1] =
 {
-       double linev;
-       double loadpct;
-       double bcharge;
-       double timeleft;
-       double outputv;
-       double itemp;
-       double battv;
-       double linefreq;
+       {"frequency", DS_TYPE_GAUGE, 0, NAN}
+};
+
+static data_set_t ds_frequency =
+{
+       "frequency", 1, data_source_frequency
 };
 
-#define BIG_BUF 4096
+static const char *config_keys[] =
+{
+       "Host",
+       "Port",
+       NULL
+};
+static int config_keys_num = 2;
 
-#if APCMAIN
 /* Close the network connection */
-static void net_close (int *fd)
+static int apcups_shutdown (void)
 {
        uint16_t packet_size = 0;
 
-       assert (*fd >= 0);
+       if (global_sockfd < 0)
+               return (0);
 
-       DBG ("Gracefully shutting down socket %i.", *fd);
+       DBG ("Gracefully shutting down socket %i.", global_sockfd);
 
        /* send EOF sentinel */
-       swrite (*fd, (void *) &packet_size, sizeof (packet_size));
+       swrite (global_sockfd, (void *) &packet_size, sizeof (packet_size));
 
-       close (*fd);
-       *fd = -1;
-}
-#endif /* APCMAIN */
+       close (global_sockfd);
+       global_sockfd = -1;
+
+       return (0);
+} /* int apcups_shutdown */
 
 /*     
  * Open a TCP connection to the UPS network server
@@ -297,10 +304,10 @@ static int apc_query_server (char *host, int port,
        int     n;
        char    recvline[1024];
        char   *tokptr;
+       char   *toksaveptr;
        char   *key;
        double  value;
 
-       static int sockfd   = -1;
        static complain_t compl;
 
 #if APCMAIN
@@ -309,9 +316,9 @@ static int apc_query_server (char *host, int port,
 # define PRINT_VALUE(name, val) /**/
 #endif
 
-       if (sockfd < 0)
+       if (global_sockfd < 0)
        {
-               if ((sockfd = net_open (host, NULL, port)) < 0)
+               if ((global_sockfd = net_open (host, NULL, port)) < 0)
                {
                        plugin_complain (LOG_ERR, &compl, "apcups plugin: "
                                        "Connecting to the apcupsd failed.");
@@ -324,13 +331,13 @@ static int apc_query_server (char *host, int port,
                }
        }
 
-       if (net_send (&sockfd, "status", 6) < 0)
+       if (net_send (&global_sockfd, "status", 6) < 0)
        {
                syslog (LOG_ERR, "apcups plugin: Writing to the socket failed.");
                return (-1);
        }
 
-       while ((n = net_recv (&sockfd, recvline, sizeof (recvline) - 1)) > 0)
+       while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0)
        {
                assert (n < sizeof (recvline));
                recvline[n] = '\0';
@@ -338,11 +345,12 @@ static int apc_query_server (char *host, int port,
                printf ("net_recv = `%s';\n", recvline);
 #endif /* if APCMAIN */
 
-               tokptr = strtok (recvline, " :\t");
+               toksaveptr = NULL;
+               tokptr = strtok_r (recvline, " :\t", &toksaveptr);
                while (tokptr != NULL)
                {
                        key = tokptr;
-                       if ((tokptr = strtok (NULL, " :\t")) == NULL)
+                       if ((tokptr = strtok_r (NULL, " :\t", &toksaveptr)) == NULL)
                                continue;
                        value = atof (tokptr);
 
@@ -365,7 +373,7 @@ static int apc_query_server (char *host, int port,
                        else if (strcmp ("TIMELEFT", key) == 0)
                                apcups_detail->timeleft = value;
 
-                       tokptr = strtok (NULL, ":");
+                       tokptr = strtok_r (NULL, ":", &toksaveptr);
                } /* while (tokptr != NULL) */
        }
        
@@ -374,51 +382,20 @@ static int apc_query_server (char *host, int port,
                syslog (LOG_WARNING, "apcups plugin: Error reading from socket");
                return (-1);
        }
-#if APCMAIN
-       else
-       {
-               /* close the opened socket */
-               net_close (&sockfd);
-       }
-#endif /* APCMAIN */
 
        return (0);
 }
 
-#if APCMAIN
-/*
- * This is used for testing apcups in a standalone mode.
- * Usefull for debugging.
- */
-int main (int argc, char **argv)
-{
-       /* we are not really going to use this */
-       struct apc_detail_s apcups_detail;
-
-       openlog ("apcups", LOG_PID | LOG_NDELAY | LOG_LOCAL1, LOG_USER);
-
-       if (global_host == NULL || strcmp (global_host, "0.0.0.0") == 0)
-               global_host = "localhost";
-
-       if(apc_query_server (global_host, global_port, &apcups_detail) < 0)
-       {
-               printf("apcups: Failed...\n");
-               return(-1);
-       }
-
-       return 0;
-}
-#else
-static int apcups_config (char *key, char *value)
+static int apcups_config (const char *key, const char *value)
 {
        if (strcasecmp (key, "host") == 0)
        {
-               if (global_host != NULL)
+               if (conf_host != NULL)
                {
-                       free (global_host);
-                       global_host = NULL;
+                       free (conf_host);
+                       conf_host = NULL;
                }
-               if ((global_host = strdup (value)) == NULL)
+               if ((conf_host = strdup (value)) == NULL)
                        return (1);
        }
        else if (strcasecmp (key, "Port") == 0)
@@ -429,7 +406,7 @@ static int apcups_config (char *key, char *value)
                        syslog (LOG_WARNING, "apcups plugin: Invalid port: %i", port_tmp);
                        return (1);
                }
-               global_port = port_tmp;
+               conf_port = port_tmp;
        }
        else
        {
@@ -438,68 +415,22 @@ static int apcups_config (char *key, char *value)
        return (0);
 }
 
-static void apcups_init (void)
-{
-       return;
-}
-
-static void apc_write_voltage (char *host, char *inst, char *val)
-{
-       char file[512];
-       int  status;
-
-       status = snprintf (file, 512, bvolt_file_template, inst);
-       if ((status < 1) || (status >= 512))
-               return;
-
-       rrd_update_file (host, file, val, bvolt_ds_def, bvolt_ds_num);
-}
-
-static void apc_write_charge (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, charge_file_template, val, charge_ds_def, charge_ds_num);
-}
-
-static void apc_write_percent (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, load_file_template, val, load_ds_def, load_ds_num);
-}
-
-static void apc_write_timeleft (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, time_file_template, val, time_ds_def, time_ds_num);
-}
-
-static void apc_write_temperature (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, temp_file_template, val, temp_ds_def, temp_ds_num);
-}
-
-static void apc_write_frequency (char *host, char *inst, char *val)
+static void apc_submit_generic (char *type, char *type_inst, double value)
 {
-       char file[512];
-       int  status;
-
-       status = snprintf (file, 512, freq_file_template, inst);
-       if ((status < 1) || (status >= 512))
-               return;
-
-       rrd_update_file (host, file, val, freq_ds_def, freq_ds_num);
-}
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-static void apc_submit_generic (char *type, char *inst,
-               double value)
-{
-       char buf[512];
-       int  status;
+       values[0].gauge = value;
 
-       status = snprintf (buf, 512, "%u:%f",
-                       (unsigned int) curtime, value);
-       if ((status < 1) || (status >= 512))
-               return;
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "apcups");
+       strcpy (vl.plugin_instance, "");
+       strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 
-       DBG ("plugin_submit (%s, %s, %s);", type, inst, buf);
-       plugin_submit (type, inst, buf);
+       plugin_dispatch_values (type, &vl);
 }
 
 static void apc_submit (struct apc_detail_s *apcups_detail)
@@ -507,14 +438,14 @@ static void apc_submit (struct apc_detail_s *apcups_detail)
        apc_submit_generic ("apcups_voltage",    "input",   apcups_detail->linev);
        apc_submit_generic ("apcups_voltage",    "output",  apcups_detail->outputv);
        apc_submit_generic ("apcups_voltage",    "battery", apcups_detail->battv);
-       apc_submit_generic ("apcups_charge",     "-",       apcups_detail->bcharge);
-       apc_submit_generic ("apcups_charge_pct", "-",       apcups_detail->loadpct);
-       apc_submit_generic ("apcups_timeleft",   "-",       apcups_detail->timeleft);
-       apc_submit_generic ("apcups_temp",       "-",       apcups_detail->itemp);
+       apc_submit_generic ("apcups_charge",     "",        apcups_detail->bcharge);
+       apc_submit_generic ("apcups_charge_pct", "",        apcups_detail->loadpct);
+       apc_submit_generic ("apcups_timeleft",   "",        apcups_detail->timeleft);
+       apc_submit_generic ("apcups_temp",       "",        apcups_detail->itemp);
        apc_submit_generic ("apcups_frequency",  "input",   apcups_detail->linefreq);
 }
 
-static void apcups_read (void)
+static int apcups_read (void)
 {
        struct apc_detail_s apcups_detail;
        int status;
@@ -528,10 +459,10 @@ static void apcups_read (void)
        apcups_detail.itemp    = -300.0;
        apcups_detail.linefreq =   -1.0;
   
-       status = apc_query_server (global_host == NULL
+       status = apc_query_server (conf_host == NULL
                        ? APCUPS_DEFAULT_HOST
-                       : global_host,
-                       global_port, &apcups_detail);
+                       : conf_host,
+                       conf_port, &apcups_detail);
  
        /*
         * if we did not connect then do not bother submitting
@@ -540,27 +471,28 @@ static void apcups_read (void)
        if (status != 0)
        {
                DBG ("apc_query_server (%s, %i) = %i",
-                               global_host == NULL
+                               conf_host == NULL
                                ? APCUPS_DEFAULT_HOST
-                               : global_host,
-                               global_port, status);
-               return;
+                               : conf_host,
+                               conf_port, status);
+               return (-1);
        }
 
        apc_submit (&apcups_detail);
+
+       return (0);
 } /* apcups_read */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, apcups_init, apcups_read, NULL);
-       plugin_register ("apcups_voltage",    NULL, NULL, apc_write_voltage);
-       plugin_register ("apcups_charge",     NULL, NULL, apc_write_charge);
-       plugin_register ("apcups_charge_pct", NULL, NULL, apc_write_percent);
-       plugin_register ("apcups_timeleft",   NULL, NULL, apc_write_timeleft);
-       plugin_register ("apcups_temp",       NULL, NULL, apc_write_temperature);
-       plugin_register ("apcups_frequency",  NULL, NULL, apc_write_frequency);
-       cf_register (MODULE_NAME, apcups_config, config_keys, config_keys_num);
-}
+       plugin_register_data_set (&ds_voltage);
+       plugin_register_data_set (&ds_percent);
+       plugin_register_data_set (&ds_timeleft);
+       plugin_register_data_set (&ds_temperature);
+       plugin_register_data_set (&ds_frequency);
 
-#endif /* if APCMAIN */
-#undef MODULE_NAME
+       plugin_register_config ("apcups", apcups_config, config_keys, config_keys_num);
+
+       plugin_register_read ("apcups", apcups_read);
+       plugin_register_shutdown ("apcups", apcups_shutdown);
+}
index 37bd5c3..29d5091 100644 (file)
@@ -1,11 +1,10 @@
 /**
  * collectd - src/apple_sensors.c
- * Copyright (C) 2006  Florian octo Forster
+ * Copyright (C) 2006,2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,8 +24,6 @@
 #include "plugin.h"
 #include "utils_debug.h"
 
-#define MODULE_NAME "apple_sensors"
-
 #if HAVE_CTYPE_H
 #  include <ctype.h>
 #endif
 static mach_port_t io_master_port = MACH_PORT_NULL;
 #endif
 
-static char *temperature_file = "apple_sensors/temperature-%s.rrd";
-static char *fanspeed_file    = "apple_sensors/fanspeed-%s.rrd";
+static data_source_t data_source_fanspeed[1] =
+{
+       {"value", DS_TYPE_GAUGE, 0, NAN}
+};
 
-static char *ds_def[] =
+static data_set_t fanspeed_ds =
 {
-       "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
-       NULL
+       "fanspeed", 1, data_source_fanspeed
 };
-static int ds_num = 1;
 
-static void as_init (void)
+static data_source_t data_source_temperature[1] =
 {
+       {"value", DS_TYPE_GAUGE, -273.15, NAN}
+};
+
+static data_set_t temperature_ds =
+{
+       "temperature", 1, data_source_temperature
+};
+
 #if IOKIT_HAVE_READ
+static int as_init (void)
+{
        kern_return_t status;
        
        if (io_master_port != MACH_PORT_NULL)
@@ -91,48 +98,35 @@ static void as_init (void)
                syslog (LOG_ERR, "IOMasterPort failed: %s",
                                mach_error_string (status));
                io_master_port = MACH_PORT_NULL;
-               return;
+               return (-1);
        }
-#endif /* IOKIT_HAVE_READ */
 
-       return;
+       return (0);
 }
 
-static void as_write (char *host, char *inst, char *val, const char *template)
+static void as_submit (const char *type, const char *type_instance,
+               double val)
 {
-       char filename[256];
-       int  status;
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       status = snprintf (filename, 256, template, inst);
-       if ((status < 1) || (status >= 256))
-               return;
+       DBG ("type = %s; type_instance = %s; val = %f;",
+                       type, type_instance, val);
 
-       rrd_update_file (host, filename, val, ds_def, ds_num);
-}
+       values[0].gauge = val;
 
-static void temperature_write (char *host, char *inst, char *val)
-{
-       as_write (host, inst, val, temperature_file);
-}
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "apple_sensors");
+       strcpy (vl.plugin_instance, "");
+       strcpy (vl.type_instance, type_instance);
 
-static void fanspeed_write (char *host, char *inst, char *val)
-{
-       as_write (host, inst, val, fanspeed_file);
+       plugin_dispatch_values (type, &vl);
 }
 
-#if IOKIT_HAVE_READ
-static void as_submit (char *type, char *inst, double value)
-{
-       char buf[128];
-
-       if (snprintf (buf, 1024, "%u:%f", (unsigned int) curtime,
-                               value) >= 128)
-               return;
-
-       plugin_submit (type, inst, buf);
-}
-
-static void as_read (void)
+static int as_read (void)
 {
        kern_return_t   status;
        io_iterator_t   iterator;
@@ -147,7 +141,7 @@ static void as_read (void)
        int    i;
 
        if (!io_master_port || (io_master_port == MACH_PORT_NULL))
-               return;
+               return (-1);
 
        status = IOServiceGetMatchingServices (io_master_port,
                        IOServiceNameMatching("IOHWSensor"),
@@ -156,7 +150,7 @@ static void as_read (void)
                {
                syslog (LOG_ERR, "IOServiceGetMatchingServices failed: %s",
                                mach_error_string (status));
-               return;
+               return (-1);
        }
 
        while ((io_obj = IOIteratorNext (iterator)))
@@ -228,17 +222,17 @@ static void as_read (void)
                if (strcmp (type, "temperature") == 0)
                {
                        value_double = ((double) value_int) / 65536.0;
-                       strncpy (type, "apple_temperature", 128);
+                       strcpy (type, "temperature");
                }
                else if (strcmp (type, "temp") == 0)
                {
                        value_double = ((double) value_int) / 10.0;
-                       strncpy (type, "apple_temperature", 128);
+                       strcpy (type, "temperature");
                }
                else if (strcmp (type, "fanspeed") == 0)
                {
                        value_double = ((double) value_int) / 65536.0;
-                       strncpy (type, "apple_fanspeed", 128);
+                       strcpy (type, "fanspeed");
                }
                else if (strcmp (type, "voltage") == 0)
                {
@@ -248,7 +242,7 @@ static void as_read (void)
                else if (strcmp (type, "adc") == 0)
                {
                        value_double = ((double) value_int) / 10.0;
-                       strncpy (type, "apple_temperature", 128);
+                       strcpy (type, "fanspeed");
                }
                else
                {
@@ -264,16 +258,18 @@ static void as_read (void)
        } /* while (iterator) */
 
        IOObjectRelease (iterator);
-}
-#else
-# define as_read NULL
+
+       return (0);
+} /* int as_read */
 #endif /* IOKIT_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, as_init, as_read, NULL);
-       plugin_register ("apple_temperature", NULL, NULL, temperature_write);
-       plugin_register ("apple_fanspeed",    NULL, NULL, fanspeed_write);
-}
+       plugin_register_data_set (&fanspeed_ds);
+       plugin_register_data_set (&temperature_ds);
 
-#undef MODULE_NAME
+#if IOKIT_HAVE_READ
+       plugin_register_init ("apple_sensors", as_init);
+       plugin_register_read ("apple_sensors", as_read);
+#endif /* IOKIT_HAVE_READ */
+}
index 2141a58..8a74b3d 100644 (file)
@@ -1,11 +1,10 @@
 /**
  * collectd - src/battery.c
- * Copyright (C) 2006  Florian octo Forster
+ * Copyright (C) 2006,2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,9 +24,6 @@
 #include "plugin.h"
 #include "utils_debug.h"
 
-#define MODULE_NAME "battery"
-#define BUFSIZE 512
-
 #if HAVE_MACH_MACH_TYPES_H
 #  include <mach/mach_types.h>
 #endif
 
 #define INVALID_VALUE 47841.29
 
-static char *battery_current_file = "battery-%s/current.rrd";
-static char *battery_voltage_file = "battery-%s/voltage.rrd";
-static char *battery_charge_file  = "battery-%s/charge.rrd";
+static data_source_t data_source_charge[1] =
+{
+       {"value", DS_TYPE_GAUGE, 0, NAN}
+};
+
+static data_set_t charge_ds =
+{
+       "charge", 1, data_source_charge
+};
+
+static data_source_t data_source_current[1] =
+{
+       {"value", DS_TYPE_GAUGE, NAN, NAN}
+};
 
-static char *ds_def_current[] =
+static data_set_t current_ds =
 {
-       "DS:current:GAUGE:"COLLECTD_HEARTBEAT":U:U",
-       NULL
+       "current", 1, data_source_current
 };
-static int ds_num_current = 1;
 
-static char *ds_def_voltage[] =
+static data_source_t data_source_voltage[1] =
 {
-       "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":U:U",
-       NULL
+       {"value", DS_TYPE_GAUGE, NAN, NAN}
 };
-static int ds_num_voltage = 1;
 
-static char *ds_def_charge[] =
+static data_set_t voltage_ds =
 {
-       "DS:charge:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       "voltage", 1, data_source_voltage
 };
-static int ds_num_charge = 1;
 
+#if BATTERY_HAVE_READ
 #if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
        /* No global variables */
 /* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
@@ -95,7 +97,7 @@ static int   battery_pmu_num = 0;
 static char *battery_pmu_file = "/proc/pmu/battery_%i";
 #endif /* KERNEL_LINUX */
 
-static void battery_init (void)
+static int battery_init (void)
 {
 #if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
        /* No init neccessary */
@@ -103,13 +105,13 @@ static void battery_init (void)
 
 #elif KERNEL_LINUX
        int len;
-       char filename[BUFSIZE];
+       char filename[128];
 
        for (battery_pmu_num = 0; ; battery_pmu_num++)
        {
-               len = snprintf (filename, BUFSIZE, battery_pmu_file, battery_pmu_num);
+               len = snprintf (filename, sizeof (filename), battery_pmu_file, battery_pmu_num);
 
-               if ((len >= BUFSIZE) || (len < 0))
+               if ((len >= sizeof (filename)) || (len < 0))
                        break;
 
                if (access (filename, R_OK))
@@ -117,90 +119,25 @@ static void battery_init (void)
        }
 #endif /* KERNEL_LINUX */
 
-       return;
-}
-
-static void battery_current_write (char *host, char *inst, char *val)
-{
-       char filename[BUFSIZE];
-       int len;
-
-       len = snprintf (filename, BUFSIZE, battery_current_file, inst);
-       if ((len >= BUFSIZE) || (len < 0))
-               return;
-
-       rrd_update_file (host, filename, val,
-                       ds_def_current, ds_num_current);
-}
-
-static void battery_voltage_write (char *host, char *inst, char *val)
-{
-       char filename[BUFSIZE];
-       int len;
-
-       len = snprintf (filename, BUFSIZE, battery_voltage_file, inst);
-       if ((len >= BUFSIZE) || (len < 0))
-               return;
-
-       rrd_update_file (host, filename, val,
-                       ds_def_voltage, ds_num_voltage);
+       return (0);
 }
 
-static void battery_charge_write (char *host, char *inst, char *val)
+static void battery_submit (const char *plugin_instance, const char *type, double value)
 {
-       char filename[BUFSIZE];
-       int len;
-
-       len = snprintf (filename, BUFSIZE, battery_charge_file, inst);
-       if ((len >= BUFSIZE) || (len < 0))
-               return;
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       rrd_update_file (host, filename, val,
-                       ds_def_charge, ds_num_charge);
-}
+       values[0].gauge = value;
 
-#if BATTERY_HAVE_READ
-static void battery_submit (char *inst, double current, double voltage, double charge)
-{
-       int len;
-       char buffer[BUFSIZE];
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "battery");
+       strcpy (vl.plugin_instance, plugin_instance);
 
-       if (current != INVALID_VALUE)
-       {
-               len = snprintf (buffer, BUFSIZE, "N:%.3f", current);
-
-               if ((len > 0) && (len < BUFSIZE))
-                       plugin_submit ("battery_current", inst, buffer);
-       }
-       else
-       {
-               plugin_submit ("battery_current", inst, "N:U");
-       }
-
-       if (voltage != INVALID_VALUE)
-       {
-               len = snprintf (buffer, BUFSIZE, "N:%.3f", voltage);
-
-               if ((len > 0) && (len < BUFSIZE))
-                       plugin_submit ("battery_voltage", inst, buffer);
-       }
-       else
-       {
-               plugin_submit ("battery_voltage", inst, "N:U");
-       }
-
-       if (charge != INVALID_VALUE)
-       {
-               len = snprintf (buffer, BUFSIZE, "N:%.3f", charge);
-
-               if ((len > 0) && (len < BUFSIZE))
-                       plugin_submit ("battery_charge", inst, buffer);
-       }
-       else
-       {
-               plugin_submit ("battery_charge", inst, "N:U");
-       }
-}
+       plugin_dispatch_values (type, &vl);
+} /* void battery_submit */
 
 #if HAVE_IOKIT_PS_IOPOWERSOURCES_H || HAVE_IOKIT_IOKITLIB_H
 double dict_get_double (CFDictionaryRef dict, char *key_string)
@@ -409,7 +346,7 @@ static void get_via_generic_iokit (double *ret_charge,
 }
 #endif /* HAVE_IOKIT_IOKITLIB_H */
 
-static void battery_read (void)
+static int battery_read (void)
 {
 #if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
        double charge  = INVALID_VALUE; /* Current charge in Ah */
@@ -429,16 +366,18 @@ static void battery_read (void)
        if ((charge_rel != INVALID_VALUE) && (charge_abs != INVALID_VALUE))
                charge = charge_abs * charge_rel / 100.0;
 
-       if ((charge != INVALID_VALUE)
-                       || (current != INVALID_VALUE)
-                       || (voltage != INVALID_VALUE))
-               battery_submit ("0", current, voltage, charge);
+       if (charge != INVALID_VALUE)
+               battery_submit ("0", "charge", charge);
+       if (current != INVALID_VALUE)
+               battery_submit ("0", "current", current);
+       if (voltage != INVALID_VALUE)
+               battery_submit ("0", "voltage", voltage);
 /* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
 
 #elif KERNEL_LINUX
        FILE *fh;
-       char buffer[BUFSIZE];
-       char filename[BUFSIZE];
+       char buffer[1024];
+       char filename[256];
        
        char *fields[8];
        int numfields;
@@ -448,24 +387,24 @@ static void battery_read (void)
 
        for (i = 0; i < battery_pmu_num; i++)
        {
-               char    batnum_str[BUFSIZE];
+               char    batnum_str[256];
                double  current = INVALID_VALUE;
                double  voltage = INVALID_VALUE;
                double  charge  = INVALID_VALUE;
                double *valptr = NULL;
 
-               len = snprintf (filename, BUFSIZE, battery_pmu_file, i);
-               if ((len >= BUFSIZE) || (len < 0))
+               len = snprintf (filename, sizeof (filename), battery_pmu_file, i);
+               if ((len >= sizeof (filename)) || (len < 0))
                        continue;
 
-               len = snprintf (batnum_str, BUFSIZE, "%i", i);
-               if ((len >= BUFSIZE) || (len < 0))
+               len = snprintf (batnum_str, sizeof (batnum_str), "%i", i);
+               if ((len >= sizeof (batnum_str)) || (len < 0))
                        continue;
 
                if ((fh = fopen (filename, "r")) == NULL)
                        continue;
 
-               while (fgets (buffer, BUFSIZE, fh) != NULL)
+               while (fgets (buffer, sizeof (buffer), fh) != NULL)
                {
                        numfields = strsplit (buffer, fields, 8);
 
@@ -495,13 +434,15 @@ static void battery_read (void)
                        }
                }
 
-               if ((current != INVALID_VALUE)
-                               || (voltage != INVALID_VALUE)
-                               || (charge  != INVALID_VALUE))
-                       battery_submit (batnum_str, current, voltage, charge);
-
                fclose (fh);
                fh = NULL;
+
+               if (charge != INVALID_VALUE)
+                       battery_submit ("0", "charge", charge);
+               if (current != INVALID_VALUE)
+                       battery_submit ("0", "current", current);
+               if (voltage != INVALID_VALUE)
+                       battery_submit ("0", "voltage", voltage);
        }
 
        if (access ("/proc/acpi/battery", R_OK | X_OK) == 0)
@@ -518,7 +459,7 @@ static void battery_read (void)
                if ((dh = opendir ("/proc/acpi/battery")) == NULL)
                {
                        syslog (LOG_ERR, "Cannot open `/proc/acpi/battery': %s", strerror (errno));
-                       return;
+                       return (-1);
                }
 
                while ((ent = readdir (dh)) != NULL)
@@ -526,8 +467,10 @@ static void battery_read (void)
                        if (ent->d_name[0] == '.')
                                continue;
 
-                       len = snprintf (filename, BUFSIZE, "/proc/acpi/battery/%s/state", ent->d_name);
-                       if ((len >= BUFSIZE) || (len < 0))
+                       len = snprintf (filename, sizeof (filename),
+                                       "/proc/acpi/battery/%s/state",
+                                       ent->d_name);
+                       if ((len >= sizeof (filename)) || (len < 0))
                                continue;
 
                        if ((fh = fopen (filename, "r")) == NULL)
@@ -545,7 +488,7 @@ static void battery_read (void)
                         * [11:00] <@tokkee> remaining capacity:      4136 mAh
                         * [11:00] <@tokkee> present voltage:         12428 mV
                         */
-                       while (fgets (buffer, BUFSIZE, fh) != NULL)
+                       while (fgets (buffer, sizeof (buffer), fh) != NULL)
                        {
                                numfields = strsplit (buffer, fields, 8);
 
@@ -585,34 +528,37 @@ static void battery_read (void)
                                        if ((fields[2] == endptr) || (errno != 0))
                                                *valptr = INVALID_VALUE;
                                }
-                       }
+                       } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
+
+                       fclose (fh);
 
                        if ((current != INVALID_VALUE) && (charging == 0))
                                        current *= -1;
 
-                       if ((current != INVALID_VALUE)
-                                       || (voltage != INVALID_VALUE)
-                                       || (charge  != INVALID_VALUE))
-                               battery_submit (ent->d_name, current, voltage, charge);
-
-                       fclose (fh);
+                       if (charge != INVALID_VALUE)
+                               battery_submit ("0", "charge", charge);
+                       if (current != INVALID_VALUE)
+                               battery_submit ("0", "current", current);
+                       if (voltage != INVALID_VALUE)
+                               battery_submit ("0", "voltage", voltage);
                }
 
                closedir (dh);
        }
 #endif /* KERNEL_LINUX */
+
+       return (0);
 }
-#else
-# define battery_read NULL
 #endif /* BATTERY_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, battery_init, battery_read, NULL);
-       plugin_register ("battery_current", NULL, NULL, battery_current_write);
-       plugin_register ("battery_voltage", NULL, NULL, battery_voltage_write);
-       plugin_register ("battery_charge",  NULL, NULL, battery_charge_write);
-}
+       plugin_register_data_set (&charge_ds);
+       plugin_register_data_set (&current_ds);
+       plugin_register_data_set (&voltage_ds);
 
-#undef BUFSIZE
-#undef MODULE_NAME
+#if BATTERY_HAVE_READ
+       plugin_register_init ("battery", battery_init);
+       plugin_register_read ("battery", battery_read);
+#endif /* BATTERY_HAVE_READ */
+}
diff --git a/src/collectd-nagios.c b/src/collectd-nagios.c
new file mode 100644 (file)
index 0000000..b7c3ffa
--- /dev/null
@@ -0,0 +1,492 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+/*
+ * This weird macro cascade forces the glibc to define `NAN'. I don't know
+ * another way to solve this, so more intelligent solutions are welcome. -octo
+ */
+#ifndef __USE_ISOC99
+# define DISABLE__USE_ISOC99 1
+# define __USE_ISOC99 1
+#endif
+#include <math.h>
+#ifdef DISABLE__USE_ISOC99
+# undef DISABLE__USE_ISOC99
+# undef __USE_ISOC99
+#endif
+
+#define RET_OKAY     0
+#define RET_WARNING  1
+#define RET_CRITICAL 2
+#define RET_UNKNOWN  3
+
+#define CON_NONE     0
+#define CON_AVERAGE  1
+#define CON_SUM      2
+
+struct range_s
+{
+       double min;
+       double max;
+       int    invert;
+};
+typedef struct range_s range_t;
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+static char *socket_file_g = NULL;
+static char *value_string_g = NULL;
+static char *hostname_g = NULL;
+
+static range_t range_critical_g;
+static range_t range_warning_g;
+static int consolitation_g = CON_NONE;
+
+static char **match_ds_g = NULL;
+static int    match_ds_num_g = 0;
+
+static int ignore_ds (const char *name)
+{
+       int i;
+
+       if (match_ds_g == NULL)
+               return (0);
+
+       for (i = 0; i < match_ds_num_g; i++)
+               if (strcasecmp (match_ds_g[i], name) == 0)
+                       return (0);
+
+       return (1);
+} /* int ignore_ds */
+
+static void parse_range (char *string, range_t *range)
+{
+       char *min_ptr;
+       char *max_ptr;
+
+       if (*string == '@')
+       {
+               range->invert = 1;
+               string++;
+       }
+
+       max_ptr = strchr (string, ':');
+       if (max_ptr == NULL)
+       {
+               min_ptr = NULL;
+               max_ptr = string;
+       }
+       else
+       {
+               min_ptr = string;
+               *max_ptr = '\0';
+               max_ptr++;
+       }
+
+       assert (max_ptr != NULL);
+
+       /* `10' == `0:10' */
+       if (min_ptr == NULL)
+               range->min = 0.0;
+       /* :10 == ~:10 == -inf:10 */
+       else if ((*min_ptr == '\0') || (*min_ptr == '~'))
+               range->min = NAN;
+       else
+               range->min = atof (min_ptr);
+
+       if ((*max_ptr == '\0') || (*max_ptr == '~'))
+               range->max = NAN;
+       else
+               range->max = atof (max_ptr);
+} /* void parse_range */
+
+int match_range (range_t *range, double value)
+{
+       int ret = 0;
+
+       if (!isnan (range->min) && (range->min > value))
+               ret = 1;
+       if (!isnan (range->max) && (range->max < value))
+               ret = 1;
+
+       return (((ret - range->invert) == 0) ? 0 : 1);
+}
+
+static int get_values (int *ret_values_num, double **ret_values,
+               char ***ret_values_names)
+{
+       struct sockaddr_un sa;
+       int status;
+       int fd;
+       FILE *fh;
+       char buffer[4096];
+
+       int values_num;
+       double *values;
+       char **values_names;
+
+       int i;
+
+       fd = socket (PF_UNIX, SOCK_STREAM, 0);
+       if (fd < 0)
+       {
+               fprintf (stderr, "socket failed: %s\n",
+                               strerror (errno));
+               return (-1);
+       }
+
+       memset (&sa, '\0', sizeof (sa));
+       sa.sun_family = AF_UNIX;
+       strncpy (sa.sun_path, socket_file_g,
+                       sizeof (sa.sun_path) - 1);
+
+       status = connect (fd, (struct sockaddr *) &sa, sizeof (sa));
+       if (status != 0)
+       {
+               fprintf (stderr, "connect failed: %s\n",
+                               strerror (errno));
+               return (-1);
+       }
+
+       fh = fdopen (fd, "r+");
+       if (fh == NULL)
+       {
+               fprintf (stderr, "fdopen failed: %s\n",
+                               strerror (errno));
+               close (fd);
+               return (-1);
+       }
+
+       fprintf (fh, "GETVAL %s/%s\n", hostname_g, value_string_g);
+       fflush (fh);
+
+       if (fgets (buffer, sizeof (buffer), fh) == NULL)
+       {
+               fprintf (stderr, "fgets failed: %s\n",
+                               strerror (errno));
+               close (fd);
+               return (-1);
+       }
+       close (fd); fd = -1;
+
+       values_num = atoi (buffer);
+       if (values_num < 1)
+               return (-1);
+
+       values = (double *) malloc (values_num * sizeof (double));
+       if (values == NULL)
+       {
+               fprintf (stderr, "malloc failed: %s\n",
+                               strerror (errno));
+               return (-1);
+       }
+
+       values_names = (char **) malloc (values_num * sizeof (char *));
+       if (values_names == NULL)
+       {
+               fprintf (stderr, "malloc failed: %s\n",
+                               strerror (errno));
+               free (values);
+               return (-1);
+       }
+
+       {
+               char *ptr = strchr (buffer, ' ') + 1;
+               char *key;
+               char *value;
+
+               i = 0;
+               while ((key = strtok (ptr, " \t")) != NULL)
+               {
+                       ptr = NULL;
+                       value = strchr (key, '=');
+                       if (value == NULL)
+                               continue;
+                       *value = '\0'; value++;
+
+                       if (ignore_ds (key) != 0)
+                               continue;
+
+                       values_names[i] = strdup (key);
+                       values[i] = atof (value);
+
+                       i++;
+                       if (i >= values_num)
+                               break;
+               }
+               values_num = i;
+       }
+
+       *ret_values_num = values_num;
+       *ret_values = values;
+       *ret_values_names = values_names;
+
+       return (0);
+} /* int get_values */
+
+static void usage (const char *name)
+{
+       fprintf (stderr, "Usage: %s <-s socket> <-n value_spec> <-H hostname> [options]\n"
+                       "\n"
+                       "Valid options are:\n"
+                       "  -s <socket>    Path to collectd's UNIX-socket.\n"
+                       "  -n <v_spec>    Value specification to get from collectd.\n"
+                       "                 Format: `plugin-instance/type-instance'\n"
+                       "  -d <ds>        Select the DS to examine. May be repeated to examine multiple\n"
+                       "                 DSes. By default all DSes are used.\n"
+                       "  -g <consol>    Method to use to consolidate several DSes.\n"
+                       "                 Valid arguments are `none', `average' and `sum'\n"
+                       "  -H <host>      Hostname to query the values for.\n"
+                       "  -c <range>     Critical range\n"
+                       "  -w <range>     Warning range\n"
+                       "\n"
+                       "Consolidation functions:\n"
+                       "  none:          Apply the warning- and critical-ranges to each data-source\n"
+                       "                 individually.\n"
+                       "  average:       Calculate the average of all matching DSes and apply the\n"
+                       "                 warning- and critical-ranges to the calculated average.\n"
+                       "  sum:           Apply the ranges to the sum of all DSes.\n"
+                       "\n", name);
+       exit (1);
+} /* void usage */
+
+int do_check_con_none (int values_num, double *values, char **values_names)
+{
+       int i;
+
+       int num_critical = 0;
+       int num_warning  = 0;
+       int num_okay = 0;
+
+       for (i = 0; i < values_num; i++)
+       {
+               if (isnan (values[i]))
+                       num_warning++;
+               else if (match_range (&range_critical_g, values[i]) != 0)
+                       num_critical++;
+               else if (match_range (&range_warning_g, values[i]) != 0)
+                       num_warning++;
+               else
+                       num_okay++;
+       }
+
+       if ((num_critical != 0) || (values_num == 0))
+       {
+               printf ("CRITICAL: %i critical, %i warning, %i okay\n",
+                               num_critical, num_warning, num_okay);
+               return (RET_CRITICAL);
+       }
+       else if (num_warning != 0)
+       {
+               printf ("WARNING: %i warning, %i okay\n",
+                               num_warning, num_okay);
+               return (RET_WARNING);
+       }
+       else
+       {
+               printf ("OKAY: %i okay\n", num_okay);
+               return (RET_OKAY);
+       }
+
+       return (RET_UNKNOWN);
+} /* int do_check_con_none */
+
+int do_check_con_average (int values_num, double *values, char **values_names)
+{
+       int i;
+       double total;
+       int total_num;
+
+       total = 0.0;
+       total_num = 0;
+       for (i = 0; i < values_num; i++)
+       {
+               if (!isnan (values[i]))
+               {
+                       total += values[i];
+                       total_num++;
+               }
+       }
+
+       if (total_num == 0)
+       {
+               printf ("WARNING: No defined values found\n");
+               return (RET_WARNING);
+       }
+
+       if (match_range (&range_critical_g, total / total_num) != 0)
+       {
+               printf ("CRITICAL: Average = %lf\n",
+                               (double) (total / total_num));
+               return (RET_CRITICAL);
+       }
+       else if (match_range (&range_warning_g, total / total_num) != 0)
+       {
+               printf ("WARNING: Average = %lf\n",
+                               (double) (total / total_num));
+               return (RET_WARNING);
+       }
+       else
+       {
+               printf ("OKAY: Average = %lf\n",
+                               (double) (total / total_num));
+               return (RET_OKAY);
+       }
+
+       return (RET_UNKNOWN);
+} /* int do_check_con_average */
+
+int do_check_con_sum (int values_num, double *values, char **values_names)
+{
+       int i;
+       double total;
+       int total_num;
+
+       total = 0.0;
+       total_num = 0;
+       for (i = 0; i < values_num; i++)
+       {
+               if (!isnan (values[i]))
+               {
+                       total += values[i];
+                       total_num++;
+               }
+       }
+
+       if (total_num == 0)
+       {
+               printf ("WARNING: No defined values found\n");
+               return (RET_WARNING);
+       }
+
+       if (match_range (&range_critical_g, total) != 0)
+       {
+               printf ("CRITICAL: Sum = %lf\n", total);
+               return (RET_CRITICAL);
+       }
+       else if (match_range (&range_warning_g, total) != 0)
+       {
+               printf ("WARNING: Sum = %lf\n", total);
+               return (RET_WARNING);
+       }
+       else
+       {
+               printf ("OKAY: Sum = %lf\n", total);
+               return (RET_OKAY);
+       }
+
+       return (RET_UNKNOWN);
+} /* int do_check_con_sum */
+
+int do_check (void)
+{
+       double  *values;
+       char   **values_names;
+       int      values_num;
+
+       if (get_values (&values_num, &values, &values_names) != 0)
+       {
+               fputs ("ERROR: Cannot get values from daemon\n", stdout);
+               return (RET_CRITICAL);
+       }
+
+       if (consolitation_g == CON_NONE)
+               return (do_check_con_none (values_num, values, values_names));
+       else if (consolitation_g == CON_AVERAGE)
+               return (do_check_con_average (values_num, values, values_names));
+       else if (consolitation_g == CON_SUM)
+               return (do_check_con_sum (values_num, values, values_names));
+
+       free (values);
+       free (values_names);
+
+       return (RET_UNKNOWN);
+}
+
+int main (int argc, char **argv)
+{
+       range_critical_g.min = NAN;
+       range_critical_g.max = NAN;
+       range_critical_g.invert = 0;
+
+       range_warning_g.min = NAN;
+       range_warning_g.max = NAN;
+       range_warning_g.invert = 0;
+
+       while (42)
+       {
+               int c;
+
+               c = getopt (argc, argv, "w:c:s:n:H:g:d:h");
+               if (c < 0)
+                       break;
+
+               switch (c)
+               {
+                       case 'c':
+                               parse_range (optarg, &range_critical_g);
+                               break;
+                       case 'w':
+                               parse_range (optarg, &range_warning_g);
+                               break;
+                       case 's':
+                               socket_file_g = optarg;
+                               break;
+                       case 'n':
+                               value_string_g = optarg;
+                               break;
+                       case 'H':
+                               hostname_g = optarg;
+                               break;
+                       case 'g':
+                               if (strcasecmp (optarg, "none") == 0)
+                                       consolitation_g = CON_NONE;
+                               else if (strcasecmp (optarg, "average") == 0)
+                                       consolitation_g = CON_AVERAGE;
+                               else if (strcasecmp (optarg, "sum") == 0)
+                                       consolitation_g = CON_SUM;
+                               else
+                                       usage (argv[0]);
+                               break;
+                       case 'd':
+                       {
+                               char **tmp;
+                               tmp = (char **) realloc (match_ds_g,
+                                               (match_ds_num_g + 1)
+                                               * sizeof (char *));
+                               if (tmp == NULL)
+                               {
+                                       fprintf (stderr, "realloc failed: %s\n",
+                                                       strerror (errno));
+                                       return (RET_UNKNOWN);
+                               }
+                               match_ds_g = tmp;
+                               match_ds_g[match_ds_num_g] = strdup (optarg);
+                               if (match_ds_g[match_ds_num_g] == NULL)
+                               {
+                                       fprintf (stderr, "strdup failed: %s\n",
+                                                       strerror (errno));
+                                       return (RET_UNKNOWN);
+                               }
+                               match_ds_num_g++;
+                               break;
+                       }
+                       default:
+                               usage (argv[0]);
+               } /* switch (c) */
+       }
+
+       if ((socket_file_g == NULL) || (value_string_g == NULL)
+                       || (hostname_g == NULL))
+               usage (argv[0]);
+
+       return (do_check ());
+} /* int main */
index a93cc28..68a70ba 100644 (file)
@@ -1,11 +1,10 @@
 /**
  * collectd - src/collectd.c
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 #include "plugin.h"
 #include "configfile.h"
 
-static int loop = 0;
-
+/*
+ * Global variables
+ */
+char hostname_g[DATA_MAX_NAME_LEN];
+int  interval_g;
 #if HAVE_LIBKSTAT
 kstat_ctl_t *kc;
 #endif /* HAVE_LIBKSTAT */
 
-/*
- * exported variables
- */
-time_t curtime;
-int    operating_mode;
+static int loop = 0;
 
 static void sigIntHandler (int signal)
 {
@@ -51,34 +49,84 @@ static void sigTermHandler (int signal)
        loop++;
 }
 
-static int change_basedir (char *dir)
+static int init_global_variables (void)
 {
-       int dirlen = strlen (dir);
+       const char *str;
+
+       str = global_option_get ("Hostname");
+       if (str != NULL)
+       {
+               strncpy (hostname_g, str, sizeof (hostname_g));
+       }
+       else
+       {
+               if (gethostname (hostname_g, sizeof (hostname_g)) != 0)
+               {
+                       fprintf (stderr, "`gethostname' failed and no "
+                                       "hostname was configured.\n");
+                       return (-1);
+               }
+       }
+       DBG ("hostname_g = %s;", hostname_g);
+
+       str = global_option_get ("Interval");
+       if (str == NULL)
+               str = COLLECTD_STEP;
+       interval_g = atoi (str);
+       if (interval_g <= 0)
+       {
+               fprintf (stderr, "Cannot set the interval to a correct value.\n"
+                               "Please check your settings.\n");
+               return (-1);
+       }
+       DBG ("interval_g = %i;", interval_g);
+
+       return (0);
+} /* int init_global_variables */
+
+static int change_basedir (const char *orig_dir)
+{
+       char *dir = strdup (orig_dir);
+       int dirlen;
+       int status;
+
+       if (dir == NULL)
+       {
+               syslog (LOG_ERR, "strdup failed: %s", strerror (errno));
+               return (-1);
+       }
        
+       dirlen = strlen (dir);
        while ((dirlen > 0) && (dir[dirlen - 1] == '/'))
                dir[--dirlen] = '\0';
 
        if (dirlen <= 0)
                return (-1);
 
-       if (chdir (dir) == -1)
+       status = chdir (dir);
+       free (dir);
+
+       if (status != 0)
        {
                if (errno == ENOENT)
                {
-                       if (mkdir (dir, 0755) == -1)
+                       if (mkdir (orig_dir, 0755) == -1)
                        {
-                               syslog (LOG_ERR, "mkdir (%s): %s", dir, strerror (errno));
+                               syslog (LOG_ERR, "mkdir (%s): %s", orig_dir,
+                                               strerror (errno));
                                return (-1);
                        }
-                       else if (chdir (dir) == -1)
+                       else if (chdir (orig_dir) == -1)
                        {
-                               syslog (LOG_ERR, "chdir (%s): %s", dir, strerror (errno));
+                               syslog (LOG_ERR, "chdir (%s): %s", orig_dir,
+                                               strerror (errno));
                                return (-1);
                        }
                }
                else
                {
-                       syslog (LOG_ERR, "chdir: %s", strerror (errno));
+                       syslog (LOG_ERR, "chdir (%s): %s", orig_dir,
+                                       strerror (errno));
                        return (-1);
                }
        }
@@ -143,18 +191,8 @@ static void exit_usage (char *name)
        exit (0);
 } /* static void exit_usage (char *name) */
 
-static int start_client (void)
+static int do_init (void)
 {
-       int step;
-
-       struct timeval tv_now;
-       struct timeval tv_next;
-       struct timespec ts_wait;
-
-       step = atoi (COLLECTD_STEP);
-       if (step <= 0)
-               step = 10;
-
 #if HAVE_LIBKSTAT
        kc = NULL;
        update_kstat ();
@@ -176,6 +214,16 @@ static int start_client (void)
 
        plugin_init_all ();
 
+       return (0);
+} /* int do_init () */
+
+
+static int do_loop (void)
+{
+       struct timeval tv_now;
+       struct timeval tv_next;
+       struct timespec ts_wait;
+
        while (loop == 0)
        {
                if (gettimeofday (&tv_next, NULL) < 0)
@@ -183,27 +231,27 @@ static int start_client (void)
                        syslog (LOG_ERR, "gettimeofday failed: %s", strerror (errno));
                        return (-1);
                }
-               tv_next.tv_sec += step;
+               tv_next.tv_sec += interval_g;
 
 #if HAVE_LIBKSTAT
                update_kstat ();
 #endif
-               /* `curtime' is used by many (all?) plugins as the
-                * data-sample-time passed to RRDTool */
-               curtime = time (NULL);
 
                /* Issue all plugins */
                plugin_read_all (&loop);
 
                if (gettimeofday (&tv_now, NULL) < 0)
                {
-                       syslog (LOG_ERR, "gettimeofday failed: %s", strerror (errno));
+                       syslog (LOG_ERR, "gettimeofday failed: %s",
+                                       strerror (errno));
                        return (-1);
                }
 
                if (timeval_sub_timespec (&tv_next, &tv_now, &ts_wait) != 0)
                {
-                       syslog (LOG_WARNING, "Not sleeping because `timeval_sub_timespec' returned non-zero!");
+                       syslog (LOG_WARNING, "Not sleeping because "
+                                       "`timeval_sub_timespec' returned "
+                                       "non-zero!");
                        continue;
                }
 
@@ -212,56 +260,26 @@ static int start_client (void)
                        if (errno != EINTR)
                        {
                                syslog (LOG_ERR, "nanosleep failed: %s", strerror (errno));
-                               break;
+                               return (-1);
                        }
                }
-       }
+       } /* while (loop == 0) */
 
+       DBG ("return (0);");
        return (0);
-} /* static int start_client (void) */
+} /* int do_loop */
 
-#if HAVE_LIBRRD
-static int start_server (void)
+static int do_shutdown (void)
 {
-       char *host;
-       char *type;
-       char *instance;
-       char *values;
-
-       int  error_counter = 0;
-       int  status;
-
-       while ((loop == 0) && (error_counter < 3))
-       {
-               status = network_receive (&host, &type, &instance, &values);
-
-               if (status != 0)
-               {
-                       if (status < 0)
-                               error_counter++;
-                       continue;
-               }
-               error_counter = 0;
-
-               plugin_write (host, type, instance, values);
-
-               if (host     != NULL) free (host);     host     = NULL;
-               if (type     != NULL) free (type);     type     = NULL;
-               if (instance != NULL) free (instance); instance = NULL;
-               if (values   != NULL) free (values);   values   = NULL;
-       }
-       
+       plugin_shutdown_all ();
        return (0);
-} /* static int start_server (void) */
-#endif /* HAVE_LIBRRD */
+} /* int do_shutdown */
 
 #if COLLECT_DAEMON
-static int pidfile_create (const char *file)
+static int pidfile_create (void)
 {
        FILE *fh;
-
-       if (file == NULL)
-               file = PIDFILE;
+       const char *file = global_option_get ("PIDFile");
 
        if ((fh = fopen (file, "w")) == NULL)
        {
@@ -274,14 +292,12 @@ static int pidfile_create (const char *file)
 
        return (0);
 } /* static int pidfile_create (const char *file) */
-#endif /* COLLECT_DAEMON */
 
-#if COLLECT_DAEMON
-static int pidfile_remove (const char *file)
+static int pidfile_remove (void)
 {
-       if (file == NULL) {
-               file = PIDFILE;
-       }
+       const char *file = global_option_get ("PIDFile");
+
+       DBG ("unlink (%s)", (file != NULL) ? file : "<null>");
        return (unlink (file));
 } /* static int pidfile_remove (const char *file) */
 #endif /* COLLECT_DAEMON */
@@ -290,22 +306,15 @@ int main (int argc, char **argv)
 {
        struct sigaction sigIntAction;
        struct sigaction sigTermAction;
-       char *datadir    = PKGLOCALSTATEDIR;
        char *configfile = CONFIGFILE;
+       const char *basedir;
 #if COLLECT_DAEMON
        struct sigaction sigChldAction;
-       char *pidfile    = NULL;
        pid_t pid;
        int daemonize    = 1;
 #endif
 #if COLLECT_DEBUG
-       char *logfile    = LOGFILE;
-#endif
-
-#if HAVE_LIBRRD
-       operating_mode = MODE_LOCAL;
-#else
-       operating_mode = MODE_CLIENT;
+       const char *logfile;
 #endif
 
        /* open syslog */
@@ -332,7 +341,7 @@ int main (int argc, char **argv)
                                break;
 #if COLLECT_DAEMON
                        case 'P':
-                               pidfile = optarg;
+                               global_option_set ("PIDFile", optarg);
                                break;
                        case 'f':
                                daemonize = 0;
@@ -345,7 +354,7 @@ int main (int argc, char **argv)
        } /* while (1) */
 
 #if COLLECT_DEBUG
-       if ((logfile = cf_get_option ("LogFile", LOGFILE)) != NULL)
+       if ((logfile = global_option_get ("LogFile")) != NULL)
                DBG_STARTFILE (logfile, "Debug file opened.");
 #endif
 
@@ -366,31 +375,34 @@ int main (int argc, char **argv)
         * Change directory. We do this _after_ reading the config and loading
         * modules to relative paths work as expected.
         */
-       if ((datadir = cf_get_option ("DataDir", PKGLOCALSTATEDIR)) == NULL)
+       if ((basedir = global_option_get ("BaseDir")) == NULL)
        {
-               fprintf (stderr, "Don't have a datadir to use. This should not happen. Ever.");
+               fprintf (stderr, "Don't have a basedir to use. This should not happen. Ever.");
                return (1);
        }
-       if (change_basedir (datadir))
+       else if (change_basedir (basedir))
        {
-               fprintf (stderr, "Error: Unable to change to directory `%s'.\n", datadir);
+               fprintf (stderr, "Error: Unable to change to directory `%s'.\n", basedir);
                return (1);
        }
 
+       /*
+        * Set global variables or, if that failes, exit. We cannot run with
+        * them being uninitialized. If nothing is configured, then defaults
+        * are being used. So this means that the user has actually done
+        * something wrong.
+        */
+       if (init_global_variables () != 0)
+               return (1);
+
 #if COLLECT_DAEMON
        /*
         * fork off child
         */
+       memset (&sigChldAction, '\0', sizeof (sigChldAction));
        sigChldAction.sa_handler = SIG_IGN;
        sigaction (SIGCHLD, &sigChldAction, NULL);
 
-       if ((pidfile == NULL)
-                       && ((pidfile = cf_get_option ("PIDFile", PIDFILE)) == NULL))
-       {
-               fprintf (stderr, "Cannot obtain pidfile. This shoud not happen. Ever.");
-               return (1);
-       }
-
        if (daemonize)
        {
                if ((pid = fork ()) == -1)
@@ -410,7 +422,7 @@ int main (int argc, char **argv)
                setsid ();
 
                /* Write pidfile */
-               if (pidfile_create (pidfile))
+               if (pidfile_create ())
                        exit (2);
 
                /* close standard descriptors */
@@ -439,23 +451,20 @@ int main (int argc, char **argv)
        /*
         * install signal handlers
         */
+       memset (&sigIntAction, '\0', sizeof (sigIntAction));
        sigIntAction.sa_handler = sigIntHandler;
        sigaction (SIGINT, &sigIntAction, NULL);
 
+       memset (&sigTermAction, '\0', sizeof (sigTermAction));
        sigTermAction.sa_handler = sigTermHandler;
        sigaction (SIGTERM, &sigTermAction, NULL);
 
        /*
         * run the actual loops
         */
-#if HAVE_LIBRRD
-       if (operating_mode == MODE_SERVER)
-               start_server ();
-       else /* if (operating_mode == MODE_CLIENT || operating_mode == MODE_LOCAL || operating_mode == MODE_LOG) */
-#endif
-               start_client ();
-
-       plugin_shutdown_all ();
+       do_init ();
+       do_loop ();
+       do_shutdown ();
 
 #if COLLECT_DEBUG
        if (logfile != NULL)
@@ -468,8 +477,8 @@ int main (int argc, char **argv)
 
 #if COLLECT_DAEMON
        if (daemonize)
-               pidfile_remove (pidfile);
+               pidfile_remove ();
 #endif /* COLLECT_DAEMON */
 
        return (0);
-} /* int main (int argc, char **argv) */
+} /* int main */
index b3f9963..d959493 100644 (file)
@@ -4,21 +4,15 @@
 # http://collectd.org/
 #
 
-# Select one of the following modes:
-@BUILD_WITH_RRDTOOL_TRUE@Mode Local
-#Mode Server
-@BUILD_WITH_RRDTOOL_FALSE@Mode Client
-#Mode Log
-
 # Set the IP-address(es) and UDP-port(s) to send packets to. `Listen' can be
 # used as a synonym for `Server' to make the config file more readable when in
 # server mode. The port option is optional.
 #Server ff18::efc0:4a42 25826
 #Server 239.192.74.66 25826
 
-#DataDir   /opt/collectd/var/lib/collectd
-#PIDFile   /opt/collectd/var/run/collectd.pid
-#PluginDir /opt/collectd/lib/collectd
+#BaseDir   "/opt/collectd/var/lib/collectd"
+#PIDFile   "/opt/collectd/var/run/collectd.pid"
+#PluginDir "/opt/collectd/lib/collectd"
 
 @BUILD_MODULE_APACHE_TRUE@LoadPlugin apache
 @BUILD_MODULE_APCUPS_TRUE@LoadPlugin apcups
 @BUILD_MODULE_BATTERY_TRUE@LoadPlugin battery
 @BUILD_MODULE_CPU_TRUE@LoadPlugin cpu
 @BUILD_MODULE_CPUFREQ_TRUE@LoadPlugin cpufreq
+@BUILD_MODULE_CSV_TRUE@LoadPlugin csv
 @BUILD_MODULE_DF_TRUE@LoadPlugin df
 @BUILD_MODULE_DISK_TRUE@LoadPlugin disk
 @BUILD_MODULE_DNS_TRUE@LoadPlugin dns
+@BUILD_MODULE_EMAIL_TRUE@LoadPlugin email
 @BUILD_MODULE_HDDTEMP_TRUE@LoadPlugin hddtemp
 @BUILD_MODULE_IPTABLES_TRUE@LoadPlugin iptables
 @BUILD_MODULE_IRQ_TRUE@LoadPlugin irq
 @BUILD_MODULE_MEMORY_TRUE@LoadPlugin memory
 @BUILD_MODULE_MULTIMETER_TRUE@LoadPlugin multimeter
 @BUILD_MODULE_MYSQL_TRUE@LoadPlugin mysql
+@BUILD_MODULE_NETWORK_TRUE@LoadPlugin network
 @BUILD_MODULE_NFS_TRUE@LoadPlugin nfs
 @BUILD_MODULE_NTPD_TRUE@LoadPlugin ntpd
 @BUILD_MODULE_PING_TRUE@LoadPlugin ping
 @BUILD_MODULE_PROCESSES_TRUE@LoadPlugin processes
+@BUILD_WITH_RRDTOOL_TRUE@LoadPlugin rrdtool
 @BUILD_MODULE_SENSORS_TRUE@LoadPlugin sensors
 @BUILD_MODULE_SERIAL_TRUE@LoadPlugin serial
 @BUILD_MODULE_SWAP_TRUE@LoadPlugin swap
 @BUILD_MODULE_WIRELESS_TRUE@LoadPlugin wireless
 
 #<Plugin apache>
-#      URL http://localhost/status?auto
-#      User www-user
-#      Password secret
-#      CACert /etc/ssl/ca.crt
+#      URL "http://localhost/status?auto"
+#      User "www-user"
+#      Password "secret"
+#      CACert "/etc/ssl/ca.crt"
 #</Plugin>
 
 #<Plugin apcups>
-#      Host localhost
-#      Port 3551
+#      Host "localhost"
+#      Port "3551"
+#</Plugin>
+
+#<Plugin csv>
+#      DataDir "/var/lib/collectd/csv"
 #</Plugin>
 
 #<Plugin dns>
-#      Interface eth0
-#      IgnoreSource 192.168.0.1
+#      Interface "eth0"
+#      IgnoreSource "192.168.0.1"
 #</Plugin>
 
 #<Plugin hddtemp>
-#      Host 127.0.0.1
+#      Host "127.0.0.1"
 #      Port 7634
 #</Plugin>
 
 #</Plugin>
 
 #<Plugin mbmon>
-#      Host 127.0.0.1
+#      Host "127.0.0.1"
 #      Port 411
 #</Plugin>
 
+#<Plugin network>
+#      Server "ff18::efc0:4a42" "25826"
+#      Server "239.192.74.66" "25826"
+#      Listen "ff18::efc0:4a42" "25826"
+#      Listen "239.192.74.66" "25826"
+#      TimeToLive "128"
+#</Plugin>
+
 #<Plugin ntpd>
-#      Host localhost
+#      Host "localhost"
 #      Port 123
 #</Plugin>
 
 #<Plugin mysql>
-#      Host database.serv.er
-#      User db_user
-#      Password secret
-#      Database db_name
+#      Host "database.serv.er"
+#      User "db_user"
+#      Password "secret"
+#      Database "db_name"
 #</Plugin>
 
 #<Plugin ping>
-#      Host host.foo.bar
+#      Host "host.foo.bar"
 #</Plugin>
 
 #<Plugin processes>
-#      Process name
+#      Process "name"
+#</Plugin>
+
+#<Plugin rrdtool>
+#      DataDir "/var/lib/collectd/rrd"
+#      StepSize      10
+#      HeartBeat     20
+#      RRARows     1200
+#      XFF            0.1
+#      CacheTimeout 120
+#      CacheFlush   900
 #</Plugin>
 
 ## There are two different naming schemes for the sensors plugin, to preserver
 ## backwards compatibility. The `extended naming' is prefered, but not the
 ## default for this reason. See `collectd.conf(5)' for more information.
 #<Plugin sensors>
-#      ExtendedSensorNaming false
-#      Sensor it8712-temp1
-#      Sensor it8712-fan3
-#      Sensor it8712-in8
-## -- OR --
-#      ExtendedSensorNaming true
-#      Sensor it8712-isa-0290/temperature-temp1
-#      Sensor it8712-isa-0290/fanspeed-fan3
-#      Sensor it8712-isa-0290/voltage-in8
+#      Sensor "it8712-isa-0290/temperature-temp1"
+#      Sensor "it8712-isa-0290/fanspeed-fan3"
+#      Sensor "it8712-isa-0290/voltage-in8"
 #
 #      IgnoreSelected false
 #</Plugin>
 
 #<Plugin traffic>
-#      Interface eth0
+#      Interface "eth0"
 #      IgnoreSelected false
 #</Plugin>
index 803df8b..b47fdc1 100644 (file)
@@ -4,42 +4,44 @@ collectd.conf - Configuration for the system statistics collection daemon B<coll
 
 =head1 SYNOPSIS
 
-  Mode    Client
-  DataDir /path/to/data/
-  PIDFile /path/to/pidfile/collectd.pid
-  LogFile /path/to/logfile/collectd.log
-  Server  123.123.123.123 12345
+  BaseDir "/path/to/data/"
+  PIDFile "/path/to/pidfile/collectd.pid"
+  LogFile "/path/to/logfile/collectd.log"
+  Server  "123.123.123.123" 12345
 
   LoadPlugin cpu
   LoadPlugin load
   LoadPlugin ping
 
   <Plugin ping>
-    Host example.org
-    Host provider.net
+    Host "example.org"
+    Host "provider.net"
   </Plugin>
 
 =head1 DESCRIPTION
 
 This config file controls how the system statistics collection daemon
-B<collectd> behaves. The most significant options are B<Mode>, which controlls
-if the daemon will act as client, server or will be independent in local mode,
-and B<LoadPlugin> which controls which plugins to load.
+B<collectd> behaves. The most significant option is B<LoadPlugin>, which
+controls which plugins to load. These plugins ultimately define collectd's
+behavior.
 
 The syntax of this config file is similar to the config file of the famos
 B<Apache Webserver>. Each line containes either a key-value-pair or a
 section-start or -end. Empty lines and everything after the hash-symbol `#' is
-ignored.
+ignored. Values are either string, enclosed in double-quotes,
+(floating-point-)numbers or a boolean extression, i.E<nbsp>e. either B<true> or
+B<false>. String containing of only alphanumeric characters and underscores do
+not need to be quoted.
 
 =head1 GLOBAL OPTIONS
 
 =over 4
 
-=item B<Mode> (B<Local>|B<Client>|B<Server>|B<Log>)
+=item B<BaseDir> I<Directory>
 
-Sets the operating mode. See the section B<MODES> in L<collectd(1)> for a
-description. This option determines which other options are allowed. Defaults
-to B<Local>.
+Sets the base directory. This is the directory beneath all RRD-files are
+created. Possibly more subdirectories are created. This is also the working
+directory for the daemon.
 
 =item B<LoadPlugin> I<Plugin>
 
@@ -50,52 +52,20 @@ will be mostly useless. The names of the plugins are listed in L<collectd(1)>.
 
 Sets where to write the PID file to. This file is overwritten when it exists
 and deleted when the program ist stopped. Some init-scripts might override this
-setting using the B<-P> commandline option. Available in B<all modes>.
-
-=item B<DataDir> I<Directory>
-
-Sets the data directory. This is the directory beneath all RRD-files are
-created. Possibly more subdirectories are created. This is also the working
-directory for the daemon. Available in B<all modes>, though the B<Client> mode
-won't write to this directory.
+setting using the B<-P> commandline option.
 
 =item B<LogFile> I<File>
 
 Sets the file to write debugging output to. This is only used if compiled with
-debugging enabled. It's ignored otherwise. Available in B<all modes>.
-
-=item B<Listen> I<Host> [I<Port>]
-
-=item B<Server> I<Host> [I<Port>]
-
-In B<client mode> the B<Server> statement sets the server to send datagrams to.
-The statement may occur multiple times to send each datagram to multiple
-destinations.
+debugging enabled. It's ignored otherwise.
 
-In B<server mode> the B<Listen> statement sets the interfaces to bind to. When
-multiple statements are found the daemon will bind to multiple interfaces.
-
-The argument I<Host> may be a hostname, an IPv4 address or an IPv6 address. If
-the argument is a multicast address the daemon will join that multicast group.
+=item B<Interval> I<Seconds>
 
-If no B<Listen> statement is found the server tries join both, the IPv6
-multicast group and the IPv4 multicast group. If no B<Server> statement is
-found the client will try to send data to the IPv6 multicast group first. If
-that failes the client will try the IPv4 multicast group.
-
-The default IPv6 multicast group is C<ff18::efc0:4a42>. The default IPv4
-multicast group is C<239.192.74.66>.
-
-The optional I<Port> argument sets the port to use. It can either be given
-using a numeric port number or a service name. If the argument is omited the
-default port B<25826> is assumed.
-
-=item B<TimeToLive> I<1-255>
-
-Set the time-to-live of sent packets. This applies to all, unicast and
-multicast, and IPv4 and IPv6 packets. The default is to not change this value.
-That means that multicast packets will be sent with a TTL of C<1> (one) on most
-operating systems.
+Configures the interval in which to query the read plugins. Obviously smaller
+values lead to a higher system load produces by collectd, while higher values
+lead to more coarse statistics. Please note that changing this value may render
+your RRD-files unuseable, if you use the C<rrdtool plugin>. You have been
+warned.
 
 =back
 
@@ -164,6 +134,17 @@ TCP-Port to connect to. Defaults to B<3551>.
 
 =back
 
+=head2 Plugin C<csv>
+
+=over 4
+
+=item B<DataDir> I<Directory>
+
+Set the directory to store RRD-files under. Per default RRD-files are generated
+beneath the daemon's working directory, i.E<nbsp>e. the B<BaseDir>.
+
+=back
+
 =head2 Plugin C<df>
 
 =over 4
@@ -279,20 +260,6 @@ TCP-Port to connect to. Defaults to B<411>.
 
 =back
 
-=head2 Plugin C<ntpd>
-
-=over 4
-
-=item B<Host> I<Hostname>
-
-Hostname of the host running B<ntpd>. Defaults to B<localhost>.
-
-=item B<Port> I<Port>
-
-UDP-Port to connect to. Defaults to B<123>.
-
-=back
-
 =head2 Plugin C<mysql>
 
 =over 4
@@ -316,6 +283,58 @@ option for what this plugin does.
 
 =back
 
+=head2 Plugin C<network>
+
+=over 4
+
+=item B<Listen> I<Host> [I<Port>]
+
+=item B<Server> I<Host> [I<Port>]
+
+The B<Server> statement sets the server to send datagrams B<to>.  The statement
+may occur multiple times to send each datagram to multiple destinations.
+
+The B<Listen> statement sets the interfaces to bind to. When multiple
+statements are found the daemon will bind to multiple interfaces.
+
+The argument I<Host> may be a hostname, an IPv4 address or an IPv6 address. If
+the argument is a multicast address the daemon will join that multicast group.
+
+If no B<Listen> statement is found the server tries join both, the default IPv6
+multicast group and the default IPv4 multicast group. If no B<Server> statement
+is found the client will try to send data to the IPv6 multicast group first. If
+that failes the client will try the IPv4 multicast group.
+
+The default IPv6 multicast group is C<ff18::efc0:4a42>. The default IPv4
+multicast group is C<239.192.74.66>.
+
+The optional I<Port> argument sets the port to use. It can either be given
+using a numeric port number or a service name. If the argument is omited the
+default port B<25826> is assumed.
+
+=item B<TimeToLive> I<1-255>
+
+Set the time-to-live of sent packets. This applies to all, unicast and
+multicast, and IPv4 and IPv6 packets. The default is to not change this value.
+That means that multicast packets will be sent with a TTL of C<1> (one) on most
+operating systems.
+
+=back
+
+=head2 Plugin C<ntpd>
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname of the host running B<ntpd>. Defaults to B<localhost>.
+
+=item B<Port> I<Port>
+
+UDP-Port to connect to. Defaults to B<123>.
+
+=back
+
 =head2 Plugin C<ping>
 
 =over 4
@@ -331,65 +350,94 @@ Sets the Time-To-Live of generated ICMP packets.
 
 =back
 
+=head2 Plugin C<rrdtool>
+
+You can use the settings B<StepSize>, B<HeartBeat>, B<RRARows>, and B<XFF> to
+finetune your RRD-files. Please read L<rrdcreate(1)> if you encounter problems
+using these settings. If you don't want to dive into the depths of RRDTool, you
+can savely ignore these settings.
+
+=over 4
+
+=item B<DataDir> I<Directory>
+
+Set the directory to store CSV-files under. Per default CSV-files are generated
+beneath the daemon's working directory, i.E<nbsp>e. the B<BaseDir>.
+
+=item B<StepSize> I<Seconds>
+
+Sets the stepsize of newly created RRD-files. Ideally (and per default) this
+setting is identical to the global B<Interval>-option and should not be
+smaller. If unsure, don't set this option.
+
+=item B<HeartBeat> I<Seconds>
+
+Sets the heartbeat of newly created RRD-files. Ideally (and per default) this
+setting is bigger than the B<Interval>-setting. If unsure, don't set this
+option.
+
+=item B<RRARows> I<NumRows>
+
+The C<rrdtool plugin> calculates the number of PDPs per CDP based on the
+B<StepSize>, this setting and a timespan. This plugin creates RRD-files with
+three times five RRAs, i. e. five RRAs with the CFs B<MIN>, B<AVERAGE>, and
+B<MAX>. The five RRAs are optimized for graphs covering one hour, one day, one
+week, one month, and one year.
+
+So for each timespan, it calculates how many PDPs need to be consolidated into
+one CDP by calculating:
+  number of PDPs = timespan / (stepsize * rrarows)
+
+Bottom line is, set this no smaller than the width of you graphs in pixels.
+
+=item B<XFF> I<Factor>
+
+Set the "XFiles Factor". This is mostly interesting if you set B<StepSize>
+bigger than B<Interval>. If unsure, don't set this option.
+
+=item B<CacheFlush> I<Seconds>
+
+When the C<rrdtool plugin> uses a cache (by setting B<CacheTimeout>, see below)
+it writes all values for a certain RRD-file if the oldest value is older than
+(or equal to) the number of seconds specified. If some RRD-file is not updated
+anymore for some reason (the computer was shut down, the network is broken,
+etc.) some values may still be in the cache. If B<CacheFlush> is set, then the
+entire cache is searched for entries older than B<CacheTimeout> seconds and
+written to disk every I<Seconds> seconds. Since this is kind of expensive and
+does nothing under normal circumstances, this value should not be too small.
+900 seconds might be a good value, though setting this to 7200 seconds doesn't
+normally do much harm either.
+
+=item B<CacheTimeout> I<Seconds>
+
+If this option is set to a value greater than zero, the C<rrdtool plugin> will
+save values in a cache, as described above. Writing multiple values at once
+reduces IO-operations and thus lessens the load produced by updating the files.
+The tradeoff is that the graphs kind of "drag behind" and that more memory is
+used.
+
+=back
+
 =head2 Plugin C<sensors>
 
 =over 4
 
-=item B<ExtendedSensorNaming> I<true>|I<false>
-
-If set to I<true> this option switches on the extended sensors and RRD-files
-naming. This option exists to preserve backwards compatibility. It is
-recommended that you set this option to I<true>. The default is I<false> to
-maintain compatibility only.
-
-Sensors get names like I<chip-bus-address/type-feature> (e.g.
-I<it8712-isa-0290/voltage-in1>) and RRD files are therefore stored in a
-standalone directory inside the B<DataDir> directory and get names like
-I<lm_sensors-chip-bus-address/type-feature.rrd> (e.g.
-I<lm_sensors-it8712-isa-0290/voltage-in1.rrd>).
-
-The B<ExtendedSensorNaming> option breaks the compatibility with previous
-sensors and RRD files naming and the place where RRDs are stored. If you turn
-it on, the plugin will create new RRD files in a standalone directory inside
-the B<DataDir> directory and without previous history. You can rename ``old''
-RRD-files to preserve already collected statistics, because the file layout
-hasn't changed. If you have two chips of the same type, you need to use
-B<ExtendedSensorNaming> in order to collect information from both chips.
-
-If not set or set to I<false>, the extended naming is not active. Sensors get
-names like I<chip-feature> (e.g. I<it8712-in1>) and RRD files are stored in the
-main B<DataDir> directory and get names like I<sensors-chip-feature.rrd> (e.g.
-I<sensors-it8712-in1.rrd>).  You simply continue using the plugin the old way
-and additionally also getting data for newly added sensors in this mode.
-
-=item B<Sensor> I<chip-feature> or B<Sensor> I<chip-bus-address/type-feature>
-
-Both option modes select the name of the sensor which you want to collect.
-The naming scheme is dependent on the state of the B<ExtendedSensorNaming>
-option (see previous option). Both option modes can also deselect the
-sensor according to the B<IgnoreSelected> option (see below).
-
-For example the option "B<Sensor> I<it8712-in1>" will cause the collectd
-to gather data for the voltage sensor I<in1> of the I<it8712> chip in case
-of the B<ExtendedSensorNaming> option is set to I<false>.
-
-And likewise the option "B<Sensor> I<it8712-isa-0290/voltage-in1>" will
-cause the collectd to gather data for the voltage sensor I<in1> of the I<it8712>
-on the isa bus at the address 0290 in case of the B<ExtendedSensorNaming>
-option set to I<true>.
+=item B<Sensor> I<chip-bus-address/type-feature>
 
-=item B<IgnoreSelected> I<true>|I<false>
+Selects the name of the sensor which you want to collect or ignore, depending
+on the B<IgnoreSelected> below. For example, the option "B<Sensor>
+I<it8712-isa-0290/voltage-in1>" will cause collectd to gather data for the
+voltage sensor I<in1> of the I<it8712> on the isa bus at the address 0290.
 
-If no configuration if given, the B<sensors>-plugin will collect data from
-all sensors. This may not be practical, especially for uninteresting sensors.
-Thus, you can use the B<Sensor>-option to pick the sensors you're
-interested in. Sometimes, however, it's easier/prefered to collect all
-sensors I<except> a few ones. This option enables you to
-do that: By setting B<IgnoreSelected> to I<true> the effect of
-B<Sensor> is inversed: All selected sensors are ignored and all
-other sensors are collected.
+=item B<IgnoreSelected> I<true>|I<false>
 
-back
+If no configuration if given, the B<sensors>-plugin will collect data from all
+sensors. This may not be practical, especially for uninteresting sensors.
+Thus, you can use the B<Sensor>-option to pick the sensors you're interested
+in. Sometimes, however, it's easier/prefered to collect all sensors I<except> a
+few ones. This option enables you to do that: By setting B<IgnoreSelected> to
+I<true> the effect of B<Sensor> is inversed: All selected sensors are ignored
+and all other sensors are collected.
 
 =back
 
index a5c8169..7bf2f56 100644 (file)
@@ -4,8 +4,7 @@
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 # define assert(...) /* nop */
 #endif
 
+#if NAN_STATIC_DEFAULT
+# include <math.h>
+/* #endif NAN_STATIC_DEFAULT*/
+#elif NAN_STATIC_ISOC
+# ifndef __USE_ISOC99
+#  define DISABLE_ISOC99 1
+#  define __USE_ISOC99 1
+# endif /* !defined(__USE_ISOC99) */
+# include <math.h>
+# if DISABLE_ISOC99
+#  undef DISABLE_ISOC99
+#  undef __USE_ISOC99
+# endif /* DISABLE_ISOC99 */
+/* #endif NAN_STATIC_ISOC */
+#elif NAN_ZERO_ZERO
+# include <math.h>
+# define NAN (0.0 / 0.0)
+# ifndef isnan
+#  define isnan(f) ((f) != (f))
+# endif /* !defined(isnan) */
+#endif /* NAN_ZERO_ZERO */
+
 #if HAVE_DIRENT_H
 # include <dirent.h>
 # define NAMLEN(dirent) strlen((dirent)->d_name)
 #  define COLLECTD_XFF 0.1
 #endif
 
-extern time_t curtime;
-
-#ifdef HAVE_LIBRRD
-extern int operating_mode;
-#endif
+#define STATIC_ARRAY_LEN(array) (sizeof (array) / sizeof ((array)[0]))
 
-/* int main (int argc, char **argv); */
+extern char hostname_g[];
+extern int  interval_g;
 
 #endif /* COLLECTD_H */
index 5487b32..922bd15 100644 (file)
@@ -1,21 +1,19 @@
 /**
  * collectd - src/common.c
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
- * This program is free software; you can redistribute it and/
- * or modify it under the terms of the GNU General Public Li-
- * cence as published by the Free Software Foundation; either
- * version 2 of the Licence, or any later version.
+ * 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; only version 2 of the License is applicable.
  *
- * This program is distributed in the hope that it will be use-
- * ful, but WITHOUT ANY WARRANTY; without even the implied war-
- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public Licence for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
  *
  * Authors:
  *   Florian octo Forster <octo at verplant.org>
 #  include <math.h>
 #endif
 
-extern int operating_mode;
+/* for ntohl and htonl */
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
 
 #ifdef HAVE_LIBKSTAT
 extern kstat_ctl_t *kc;
 #endif
 
-#ifdef HAVE_LIBRRD
-#if 0
-static char *rra_def[] =
-{
-               "RRA:AVERAGE:0.0:1:1500",
-               "RRA:AVERAGE:0.2:6:1500",
-               "RRA:AVERAGE:0.1:180:1680",
-               "RRA:AVERAGE:0.1:2160:1520",
-               "RRA:MIN:0.0:1:1500",
-               "RRA:MIN:0.2:6:1500",
-               "RRA:MIN:0.1:180:1680",
-               "RRA:MIN:0.1:2160:1520",
-               "RRA:MAX:0.0:1:1500",
-               "RRA:MAX:0.2:6:1500",
-               "RRA:MAX:0.1:180:1680",
-               "RRA:MAX:0.1:2160:1520",
-               NULL
-};
-static int rra_num = 12;
-#endif
-
-static int rra_timespans[] =
-{
-       3600,
-       86400,
-       604800,
-       2678400,
-       31622400,
-       0
-};
-static int rra_timespans_num = 5;
-
-static char *rra_types[] =
-{
-       "AVERAGE",
-       "MIN",
-       "MAX",
-       NULL
-};
-static int rra_types_num = 3;
-#endif /* HAVE_LIBRRD */
-
 void sstrncpy (char *d, const char *s, int len)
 {
        strncpy (d, s, len);
@@ -193,10 +152,12 @@ int strsplit (char *string, char **fields, size_t size)
 {
        size_t i;
        char *ptr;
+       char *saveptr;
 
        i = 0;
        ptr = string;
-       while ((fields[i] = strtok (ptr, " \t")) != NULL)
+       saveptr = NULL;
+       while ((fields[i] = strtok_r (ptr, " \t", &saveptr)) != NULL)
        {
                ptr = NULL;
                i++;
@@ -320,7 +281,7 @@ int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct times
        return (0);
 }
 
-static int check_create_dir (const char *file_orig)
+int check_create_dir (const char *file_orig)
 {
        struct stat statbuf;
 
@@ -330,7 +291,9 @@ static int check_create_dir (const char *file_orig)
        char *fields[16];
        int   fields_num;
        char *ptr;
+       char *saveptr;
        int   last_is_file = 1;
+       int   path_is_absolute = 0;
        int   len;
        int   i;
 
@@ -351,9 +314,11 @@ static int check_create_dir (const char *file_orig)
         */
        if (file_orig[len - 1] == '/')
                last_is_file = 0;
+       if (file_orig[0] == '/')
+               path_is_absolute = 1;
 
        /*
-        * Create a copy for `strtok' to destroy
+        * Create a copy for `strtok_r' to destroy
         */
        strncpy (file_copy, file_orig, 512);
        file_copy[511] = '\0';
@@ -363,8 +328,9 @@ static int check_create_dir (const char *file_orig)
         * remove leading and trailing slashes..
         */
        ptr = file_copy;
+       saveptr = NULL;
        fields_num = 0;
-       while ((fields[fields_num] = strtok (ptr, "/")) != NULL)
+       while ((fields[fields_num] = strtok_r (ptr, "/", &saveptr)) != NULL)
        {
                ptr = NULL;
                fields_num++;
@@ -392,7 +358,9 @@ static int check_create_dir (const char *file_orig)
                /*
                 * Join the components together again
                 */
-               if (strjoin (dir, dir_len, fields, i + 1, "/") < 0)
+               dir[0] = '/';
+               if (strjoin (dir + path_is_absolute, dir_len - path_is_absolute,
+                                       fields, i + 1, "/") < 0)
                {
                        syslog (LOG_ERR, "strjoin failed: `%s', component #%i", file_orig, i);
                        return (-1);
@@ -424,338 +392,6 @@ static int check_create_dir (const char *file_orig)
        return (0);
 }
 
-/* * * * *
- * Magic *
- * * * * */
-#if HAVE_LIBRRD
-static int rra_get (char ***ret)
-{
-       static char **rra_def = NULL;
-       static int rra_num = 0;
-
-       int rra_max = rra_timespans_num * rra_types_num;
-
-       int step;
-       int rows;
-       int span;
-
-       int cdp_num;
-       int cdp_len;
-       int i, j;
-
-       char buffer[64];
-
-       if ((rra_num != 0) && (rra_def != NULL))
-       {
-               *ret = rra_def;
-               return (rra_num);
-       }
-
-       if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
-               return (-1);
-       memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
-
-       step = atoi (COLLECTD_STEP);
-       rows = atoi (COLLECTD_ROWS);
-
-       if ((step <= 0) || (rows <= 0))
-       {
-               *ret = NULL;
-               return (-1);
-       }
-
-       cdp_len = 0;
-       for (i = 0; i < rra_timespans_num; i++)
-       {
-               span = rra_timespans[i];
-
-               if ((span / step) < rows)
-                       continue;
-
-               if (cdp_len == 0)
-                       cdp_len = 1;
-               else
-                       cdp_len = (int) floor (((double) span) / ((double) (rows * step)));
-
-               cdp_num = (int) ceil (((double) span) / ((double) (cdp_len * step)));
-
-               for (j = 0; j < rra_types_num; j++)
-               {
-                       if (rra_num >= rra_max)
-                               break;
-
-                       if (snprintf (buffer, sizeof(buffer), "RRA:%s:%3.1f:%u:%u",
-                                               rra_types[j], COLLECTD_XFF,
-                                               cdp_len, cdp_num) >= sizeof (buffer))
-                       {
-                               syslog (LOG_ERR, "rra_get: Buffer would have been truncated.");
-                               continue;
-                       }
-
-                       rra_def[rra_num++] = sstrdup (buffer);
-               }
-       }
-
-#if COLLECT_DEBUG
-       DBG ("rra_num = %i", rra_num);
-       for (i = 0; i < rra_num; i++)
-               DBG ("  %s", rra_def[i]);
-#endif
-
-       *ret = rra_def;
-       return (rra_num);
-}
-#endif /* HAVE_LIBRRD */
-
-static int log_create_file (char *filename, char **ds_def, int ds_num)
-{
-       FILE *log;
-       int i;
-
-       if (check_create_dir (filename))
-               return (-1);
-
-       log = fopen (filename, "w");
-       if (log == NULL)
-       {
-               syslog (LOG_WARNING, "Failed to create %s: %s", filename,
-                               strerror(errno));
-               return (-1);
-       }
-
-       fprintf (log, "epoch");
-       for (i = 0; i < ds_num; i++)
-       {
-               char *name;
-               char *tmp;
-
-               name = strchr (ds_def[i], ':');
-               if (name == NULL)
-               {
-                       syslog (LOG_WARNING, "Invalid DS definition '%s' for %s",
-                                       ds_def[i], filename);
-                       fclose(log);
-                       remove(filename);
-                       return (-1);
-               }
-
-               name += 1;
-               tmp = strchr (name, ':');
-               if (tmp == NULL)
-               {
-                       syslog (LOG_WARNING, "Invalid DS definition '%s' for %s",
-                                       ds_def[i], filename);
-                       fclose(log);
-                       remove(filename);
-                       return (-1);
-               }
-
-               /* The `%.*s' is needed because there is no null-byte behind
-                * the name. */
-               fprintf(log, ",%.*s", (int) (tmp - name), name);
-       }
-       fprintf(log, "\n");
-       fclose(log);
-
-       return 0;
-}
-
-static int log_update_file (char *host, char *file, char *values,
-               char **ds_def, int ds_num)
-{
-       char *tmp;
-       FILE *fp;
-       struct stat statbuf;
-       char full_file[1024];
-
-       /* Cook the values a bit: Substitute colons with commas */
-       strsubstitute (values, ':', ',');
-
-       /* host == NULL => local mode */
-       if (host != NULL)
-       {
-               if (snprintf (full_file, 1024, "%s/%s", host, file) >= 1024)
-                       return (-1);
-       }
-       else
-       {
-               if (snprintf (full_file, 1024, "%s", file) >= 1024)
-                       return (-1);
-       }
-
-       strncpy (full_file, file, 1024);
-
-       tmp = full_file + strlen (full_file) - 4;
-       assert ((tmp != NULL) && (tmp > full_file));
-
-       /* Change the filename for logfiles. */
-       if (strncmp (tmp, ".rrd", 4) == 0)
-       {
-               time_t now;
-               struct tm *tm;
-
-               /* TODO: Find a way to minimize the calls to `localtime', since
-                * they are pretty expensive.. */
-               now = time (NULL);
-               tm = localtime (&now);
-
-               strftime (tmp, 1024 - (tmp - full_file), "-%Y-%m-%d", tm);
-
-               /* `localtime(3)' returns a pointer to static data,
-                * therefore the pointer may not be free'd. */
-       }
-       else
-               DBG ("The filename ends with `%s' which is unexpected.", tmp);
-
-       if (stat (full_file, &statbuf) == -1)
-       {
-               if (errno == ENOENT)
-               {
-                       if (log_create_file (full_file, ds_def, ds_num))
-                               return (-1);
-               }
-               else
-               {
-                       syslog (LOG_ERR, "stat %s: %s", full_file, strerror (errno));
-                       return (-1);
-               }
-       }
-       else if (!S_ISREG (statbuf.st_mode))
-       {
-               syslog (LOG_ERR, "stat %s: Not a regular file!", full_file);
-               return (-1);
-       }
-
-
-       fp = fopen (full_file, "a");
-       if (fp == NULL)
-       {
-               syslog (LOG_WARNING, "Failed to append to %s: %s", full_file,
-                               strerror(errno));
-               return (-1);
-       }
-       fprintf(fp, "%s\n", values);
-       fclose(fp);
-
-       return (0);
-} /* int log_update_file */
-
-#if HAVE_LIBRRD
-static int rrd_create_file (char *filename, char **ds_def, int ds_num)
-{
-       char **argv;
-       int argc;
-       char **rra_def;
-       int rra_num;
-       int i, j;
-       int status = 0;
-
-       if (check_create_dir (filename))
-               return (-1);
-
-       if ((rra_num = rra_get (&rra_def)) < 1)
-       {
-               syslog (LOG_ERR, "rra_create failed: Could not calculate RRAs");
-               return (-1);
-       }
-
-       argc = ds_num + rra_num + 4;
-
-       if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
-       {
-               syslog (LOG_ERR, "rrd_create failed: %s", strerror (errno));
-               return (-1);
-       }
-
-       argv[0] = "create";
-       argv[1] = filename;
-       argv[2] = "-s";
-       argv[3] = COLLECTD_STEP;
-
-       j = 4;
-       for (i = 0; i < ds_num; i++)
-               argv[j++] = ds_def[i];
-       for (i = 0; i < rra_num; i++)
-               argv[j++] = rra_def[i];
-       argv[j] = NULL;
-
-       optind = 0; /* bug in librrd? */
-       rrd_clear_error ();
-       if (rrd_create (argc, argv) == -1)
-       {
-               syslog (LOG_ERR, "rrd_create failed: %s: %s", filename, rrd_get_error ());
-               status = -1;
-       }
-
-       free (argv);
-
-       return (status);
-}
-#endif /* HAVE_LIBRRD */
-
-int rrd_update_file (char *host, char *file, char *values,
-               char **ds_def, int ds_num)
-{
-#if HAVE_LIBRRD
-       struct stat statbuf;
-       char full_file[1024];
-       char *argv[4] = { "update", full_file, values, NULL };
-#endif /* HAVE_LIBRRD */
-
-       /* I'd rather have a function `common_update_file' to make this
-        * decission, but for that we'd need to touch all plugins.. */
-       if (operating_mode == MODE_LOG)
-               return (log_update_file (host, file, values,
-                                       ds_def, ds_num));
-
-#if HAVE_LIBRRD
-       /* host == NULL => local mode */
-       if (host != NULL)
-       {
-               if (snprintf (full_file, 1024, "%s/%s", host, file) >= 1024)
-                       return (-1);
-       }
-       else
-       {
-               if (snprintf (full_file, 1024, "%s", file) >= 1024)
-                       return (-1);
-       }
-
-       if (stat (full_file, &statbuf) == -1)
-       {
-               if (errno == ENOENT)
-               {
-                       if (rrd_create_file (full_file, ds_def, ds_num))
-                               return (-1);
-               }
-               else
-               {
-                       syslog (LOG_ERR, "stat %s: %s", full_file, strerror (errno));
-                       return (-1);
-               }
-       }
-       else if (!S_ISREG (statbuf.st_mode))
-       {
-               syslog (LOG_ERR, "stat %s: Not a regular file!", full_file);
-               return (-1);
-       }
-
-       optind = 0; /* bug in librrd? */
-       rrd_clear_error ();
-       if (rrd_update (3, argv) == -1)
-       {
-               syslog (LOG_WARNING, "rrd_update failed: %s: %s", full_file, rrd_get_error ());
-               return (-1);
-       }
-       return (0);
-/* #endif HAVE_LIBRRD */
-
-#else
-       syslog (LOG_ERR, "`rrd_update_file' was called, but collectd isn't linked against librrd!");
-       return (-1);
-#endif
-}
-
 #ifdef HAVE_LIBKSTAT
 int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name)
 {
@@ -841,3 +477,21 @@ long long get_kstat_value (kstat_t *ksp, char *name)
        return (retval);
 }
 #endif /* HAVE_LIBKSTAT */
+
+unsigned long long ntohll (unsigned long long n)
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+       return (n);
+#else
+       return (((unsigned long long) ntohl (n)) << 32) + ntohl (n >> 32);
+#endif
+}
+
+unsigned long long htonll (unsigned long long n)
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+       return (n);
+#else
+       return (((unsigned long long) htonl (n)) << 32) + htonl (n >> 32);
+#endif
+}
index 2be2ff5..9164cc2 100644 (file)
@@ -1,21 +1,19 @@
 /**
  * collectd - src/common.h
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
- * This program is free software; you can redistribute it and/
- * or modify it under the terms of the GNU General Public Li-
- * cence as published by the Free Software Foundation; either
- * version 2 of the Licence, or any later version.
+ * 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; only version 2 of the License is applicable.
  *
- * This program is distributed in the hope that it will be use-
- * ful, but WITHOUT ANY WARRANTY; without even the implied war-
- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public Licence for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
  *
  * Authors:
  *   Florian octo Forster <octo at verplant.org>
@@ -33,6 +31,8 @@
        } \
        (ptr) = NULL
 
+#define STATIC_ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a)))
+
 void sstrncpy(char *d, const char *s, int len);
 char *sstrdup(const char *s);
 void *smalloc(size_t size);
@@ -145,12 +145,14 @@ int escape_slashes (char *buf, int buf_len);
 /* FIXME: `timeval_sub_timespec' needs a description */
 int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret);
 
-int rrd_update_file (char *host, char *file, char *values,
-               char **ds_def, int ds_num);
+int check_create_dir (const char *file_orig);
 
 #ifdef HAVE_LIBKSTAT
 int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name);
 long long get_kstat_value (kstat_t *ksp, char *name);
 #endif
 
+unsigned long long ntohll (unsigned long long n);
+unsigned long long htonll (unsigned long long n);
+
 #endif /* COMMON_H */
index 40b46fa..a5ae496 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "collectd.h"
 
-#include "libconfig/libconfig.h"
+#include "liboconfig/oconfig.h"
 
 #include "common.h"
 #include "plugin.h"
 #include "network.h"
 #include "utils_debug.h"
 
-#define SHORTOPT_NONE 0
-
-#define ERR_NOT_NESTED "Sections cannot be nested.\n"
-#define ERR_SECTION_ONLY "`%s' can only be used as section.\n"
-#define ERR_NEEDS_ARG "Section `%s' needs an argument.\n"
-#define ERR_NEEDS_SECTION "`%s' can only be used within a section.\n"
-
 #define ESCAPE_NULL(str) ((str) == NULL ? "(null)" : (str))
 
-#define DEBUG_CALLBACK(shortvar, var, arguments, value) \
-       DBG("shortvar = %s, var = %s, arguments = %s, value = %s, ...", \
-                       ESCAPE_NULL(shortvar), \
-                       ESCAPE_NULL(var), \
-                       ESCAPE_NULL(arguments), \
-                       ESCAPE_NULL(value))
-
-extern int operating_mode;
-
+/*
+ * Private types
+ */
 typedef struct cf_callback
 {
-       char  *type;
-       int  (*callback) (char *, char *);
-       char **keys;
+       const char  *type;
+       int  (*callback) (const char *, const char *);
+       const char **keys;
        int    keys_num;
        struct cf_callback *next;
 } cf_callback_t;
 
-static cf_callback_t *first_callback = NULL;
+typedef struct cf_value_map_s
+{
+       char *key;
+       int (*func) (const oconfig_item_t *);
+} cf_value_map_t;
 
-typedef struct cf_mode_item
+typedef struct cf_global_option_s
 {
        char *key;
        char *value;
-       int   mode;
-} cf_mode_item_t;
+       char *def;
+} cf_global_option_t;
+
+/*
+ * Prototypes of callback functions
+ */
+static int dispatch_value_plugindir (const oconfig_item_t *ci);
+static int dispatch_value_loadplugin (const oconfig_item_t *ci);
 
-/* TODO
- * - LogFile
+/*
+ * Private variables
  */
-static cf_mode_item_t cf_mode_list[] =
+static cf_callback_t *first_callback = NULL;
+
+static cf_value_map_t cf_value_map[] =
 {
-       {"TimeToLive",  NULL, MODE_CLIENT                           },
-       {"PIDFile",     NULL, MODE_CLIENT | MODE_SERVER | MODE_LOCAL | MODE_LOG },
-       {"DataDir",     NULL, MODE_CLIENT | MODE_SERVER | MODE_LOCAL | MODE_LOG },
-       {"LogFile",     NULL, MODE_CLIENT | MODE_SERVER | MODE_LOCAL | MODE_LOG }
+       {"PluginDir",  dispatch_value_plugindir},
+       {"LoadPlugin", dispatch_value_loadplugin}
 };
-static int cf_mode_num = 4;
+static int cf_value_map_num = STATIC_ARRAY_LEN (cf_value_map);
 
-static int nesting_depth = 0;
-static char *current_module = NULL;
-
-/* `cf_register' needs this prototype */
-static int cf_callback_plugin_dispatch (const char *, const char *,
-               const char *, const char *, lc_flags_t, void *);
+static cf_global_option_t cf_global_options[] =
+{
+       {"BaseDir",   NULL, PKGLOCALSTATEDIR},
+       {"LogFile",   NULL, LOGFILE},
+       {"PIDFile",   NULL, PIDFILE},
+       {"Hostname",  NULL, NULL},
+       {"Interval",  NULL, "10"}
+};
+static int cf_global_options_num = STATIC_ARRAY_LEN (cf_global_options);
 
 /*
  * Functions to handle register/unregister, search, and other plugin related
  * stuff
  */
-static cf_callback_t *cf_search (char *type)
+static cf_callback_t *cf_search (const char *type)
 {
        cf_callback_t *cf_cb;
 
@@ -103,7 +103,8 @@ static cf_callback_t *cf_search (char *type)
        return (cf_cb);
 }
 
-static int cf_dispatch (char *type, const char *orig_key, const char *orig_value)
+static int cf_dispatch (const char *type, const char *orig_key,
+               const char *orig_value)
 {
        cf_callback_t *cf_cb;
        char *key;
@@ -150,415 +151,238 @@ static int cf_dispatch (char *type, const char *orig_key, const char *orig_value
        DBG ("return (%i)", ret);
 
        return (ret);
-}
+} /* int cf_dispatch */
 
-void cf_unregister (char *type)
+static int dispatch_global_option (const oconfig_item_t *ci)
 {
-       cf_callback_t *this, *prev;
-
-       for (prev = NULL, this = first_callback;
-                       this != NULL;
-                       prev = this, this = this->next)
-               if (strcasecmp (this->type, type) == 0)
-               {
-                       if (prev == NULL)
-                               first_callback = this->next;
-                       else
-                               prev->next = this->next;
+       if (ci->values_num != 1)
+               return (-1);
+       if (ci->values[0].type != OCONFIG_TYPE_STRING)
+               return (-1);
 
-                       free (this);
-                       break;
-               }
+       return (global_option_set (ci->key, ci->values[0].value.string));
 }
 
-void cf_register (char *type,
-               int (*callback) (char *, char *),
-               char **keys, int keys_num)
+static int dispatch_value_plugindir (const oconfig_item_t *ci)
 {
-       cf_callback_t *cf_cb;
-       char buf[64];
-       int i;
-
-       /* Remove this module from the list, if it already exists */
-       cf_unregister (type);
-
-       /* This pointer will be free'd in `cf_unregister' */
-       if ((cf_cb = (cf_callback_t *) malloc (sizeof (cf_callback_t))) == NULL)
-               return;
-
-       cf_cb->type     = type;
-       cf_cb->callback = callback;
-       cf_cb->keys     = keys;
-       cf_cb->keys_num = keys_num;
-
-       cf_cb->next = first_callback;
-       first_callback = cf_cb;
+       assert (strcasecmp (ci->key, "PluginDir") == 0);
+       
+       if (ci->values_num != 1)
+               return (-1);
+       if (ci->values[0].type != OCONFIG_TYPE_STRING)
+               return (-1);
 
-       for (i = 0; i < keys_num; i++)
-       {
-               if (snprintf (buf, 64, "Plugin.%s", keys[i]) < 64)
-               {
-                       /* This may be called multiple times for the same
-                        * `key', but apparently `lc_register_*' can handle
-                        * it.. */
-                       lc_register_callback (buf, SHORTOPT_NONE,
-                                       LC_VAR_STRING, cf_callback_plugin_dispatch,
-                                       NULL);
-               }
-               else
-               {
-                       DBG ("Key was truncated: `%s'", ESCAPE_NULL(keys[i]));
-               }
-       }
+       plugin_set_dir (ci->values[0].value.string);
+       return (0);
 }
 
-/*
- * Other query functions
- */
-char *cf_get_option (const char *key, char *def)
+static int dispatch_value_loadplugin (const oconfig_item_t *ci)
 {
-       int i;
+       assert (strcasecmp (ci->key, "LoadPlugin") == 0);
 
-       for (i = 0; i < cf_mode_num; i++)
-       {
-               if ((cf_mode_list[i].mode & operating_mode) == 0)
-                       continue;
+       if (ci->values_num != 1)
+               return (-1);
+       if (ci->values[0].type != OCONFIG_TYPE_STRING)
+               return (-1);
 
-               if (strcasecmp (cf_mode_list[i].key, key) != 0)
-                       continue;
+       return (plugin_load (ci->values[0].value.string));
+} /* int dispatch_value_loadplugin */
 
-               if (cf_mode_list[i].value != NULL)
-                       return (cf_mode_list[i].value);
-               return (def);
-       }
-
-       return (NULL);
-}
+static int dispatch_value_plugin (const char *plugin, oconfig_item_t *ci)
+{
+       char  buffer[4096];
+       char *buffer_ptr;
+       int   buffer_free;
+       int i;
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Functions for the actual parsing                                    *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+       buffer_ptr = buffer;
+       buffer_free = sizeof (buffer);
 
-/*
- * `cf_callback_mode'
- *   Chose the `operating_mode'
- *
- * Mode `value'
- */
-static int cf_callback_mode (const char *shortvar, const char *var,
-               const char *arguments, const char *value, lc_flags_t flags,
-               void *extra)
-{
-       DEBUG_CALLBACK (shortvar, var, arguments, value);
-
-       if (strcasecmp (value, "Client") == 0)
-               operating_mode = MODE_CLIENT;
-#if HAVE_LIBRRD
-       else if (strcasecmp (value, "Server") == 0)
-               operating_mode = MODE_SERVER;
-       else if (strcasecmp (value, "Local") == 0)
-               operating_mode = MODE_LOCAL;
-#else /* !HAVE_LIBRRD */
-       else if (strcasecmp (value, "Server") == 0)
+       for (i = 0; i < ci->values_num; i++)
        {
-               fprintf (stderr, "Invalid mode `Server': "
-                               "You need to link against librrd for this "
-                               "mode to be available.\n");
-               syslog (LOG_ERR, "Invalid mode `Server': "
-                               "You need to link against librrd for this "
-                               "mode to be available.");
-               return (LC_CBRET_ERROR);
-       }
-       else if (strcasecmp (value, "Local") == 0)
-       {
-               fprintf (stderr, "Invalid mode `Local': "
-                               "You need to link against librrd for this "
-                               "mode to be available.\n");
-               syslog (LOG_ERR, "Invalid mode `Local': "
-                               "You need to link against librrd for this "
-                               "mode to be available.");
-               return (LC_CBRET_ERROR);
-       }
-#endif
-       else if (strcasecmp (value, "Log") == 0)
-               operating_mode = MODE_LOG;
-       else
-       {
-               syslog (LOG_ERR, "Invalid value for config option `Mode': `%s'", value);
-               return (LC_CBRET_ERROR);
+               int status = -1;
+
+               if (ci->values[i].type == OCONFIG_TYPE_STRING)
+                       status = snprintf (buffer_ptr, buffer_free, " %s",
+                                       ci->values[i].value.string);
+               else if (ci->values[i].type == OCONFIG_TYPE_NUMBER)
+                       status = snprintf (buffer_ptr, buffer_free, " %lf",
+                                       ci->values[i].value.number);
+               else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN)
+                       status = snprintf (buffer_ptr, buffer_free, " %s",
+                                       ci->values[i].value.boolean
+                                       ? "true" : "false");
+
+               if ((status < 0) || (status >= buffer_free))
+                       return (-1);
+               buffer_free -= status;
+               buffer_ptr  += status;
        }
+       /* skip the initial space */
+       buffer_ptr = buffer + 1;
 
-       return (LC_CBRET_OKAY);
-}
-
-/*
- * `cf_callback_mode_plugindir'
- *   Change the plugin directory
- *
- * <Mode xxx>
- *   PluginDir `value'
- * </Mode>
- */
-static int cf_callback_mode_plugindir (const char *shortvar, const char *var,
-               const char *arguments, const char *value, lc_flags_t flags,
-               void *extra)
-{
-       DEBUG_CALLBACK (shortvar, var, arguments, value);
-
-       plugin_set_dir (value);
-
-       return (LC_CBRET_OKAY);
-}
+       return (cf_dispatch (plugin, ci->key, buffer_ptr));
+} /* int plugin_conf_dispatch */
 
-static int cf_callback_mode_option (const char *shortvar, const char *var,
-               const char *arguments, const char *value, lc_flags_t flags,
-               void *extra)
+static int dispatch_value (const oconfig_item_t *ci)
 {
-       cf_mode_item_t *item;
+       int ret = -2;
+       int i;
 
-       DEBUG_CALLBACK (shortvar, var, arguments, value);
+       for (i = 0; i < cf_value_map_num; i++)
+               if (strcasecmp (cf_value_map[i].key, ci->key) == 0)
+               {
+                       ret = cf_value_map[i].func (ci);
+                       break;
+               }
 
-       if (extra == NULL)
-       {
-               fprintf (stderr, "No extra..?\n");
-               return (LC_CBRET_ERROR);
-       }
+       for (i = 0; i < cf_global_options_num; i++)
+               if (strcasecmp (cf_global_options[i].key, ci->key) == 0)
+               {
+                       ret = dispatch_global_option (ci);
+                       break;
+               }
 
-       item = (cf_mode_item_t *) extra;
+       return (ret);
+} /* int dispatch_value */
 
-       if (strcasecmp (item->key, shortvar))
-       {
-               fprintf (stderr, "Wrong extra..\n");
-               return (LC_CBRET_ERROR);
-       }
+static int dispatch_block_plugin (oconfig_item_t *ci)
+{
+       int i;
+       char *name;
 
-       if ((operating_mode & item->mode) == 0)
-       {
-               fprintf (stderr, "Option `%s' is not valid in this mode!\n", shortvar);
-               return (LC_CBRET_ERROR);
-       }
+       if (strcasecmp (ci->key, "Plugin") != 0)
+               return (-1);
+       if (ci->values_num != 1)
+               return (-1);
+       if (ci->values[0].type != OCONFIG_TYPE_STRING)
+               return (-1);
 
-       if (item->value != NULL)
-       {
-               free (item->value);
-               item->value = NULL;
-       }
+       name = ci->values[0].value.string;
 
-       if ((item->value = strdup (value)) == NULL)
+       for (i = 0; i < ci->children_num; i++)
        {
-               perror ("strdup");
-               return (LC_CBRET_ERROR);
+               if (ci->children[i].children == NULL)
+                       dispatch_value_plugin (name, ci->children + i);
+               else
+                       {DBG ("No nested config blocks allow for plugins. Yet.");}
        }
 
-       return (LC_CBRET_OKAY);
+       return (0);
 }
 
-/*
- * `cf_callback_mode_loadmodule':
- *   Load a plugin.
- *
- * <Mode xxx>
- *   LoadPlugin `value'
- * </Mode>
- */
-static int cf_callback_mode_loadmodule (const char *shortvar, const char *var,
-               const char *arguments, const char *value, lc_flags_t flags,
-               void *extra)
-{
-       DEBUG_CALLBACK (shortvar, var, arguments, value);
 
-       if (plugin_load (value))
-               syslog (LOG_ERR, "plugin_load (%s): failed to load plugin", value);
+static int dispatch_block (oconfig_item_t *ci)
+{
+       if (strcasecmp (ci->key, "Plugin") == 0)
+               return (dispatch_block_plugin (ci));
 
-       /* Return `okay' even if there was an error, because it's not a syntax
-        * problem.. */
-       return (LC_CBRET_OKAY);
+       return (0);
 }
 
-static int cf_callback_socket (const char *shortvar, const char *var,
-               const char *arguments, const char *value, lc_flags_t flags,
-               void *extra)
+/* 
+ * Public functions
+ */
+int global_option_set (const char *option, const char *value)
 {
-       char *buffer;
-
-       char *fields[3];
-       int   numfields;
-
-       char *node;
-       char *service = NET_DEFAULT_PORT;
-
-       DEBUG_CALLBACK (shortvar, var, arguments, value);
-
-       buffer = strdup (value);
-       if (buffer == NULL)
-               return (LC_CBRET_ERROR);
+       int i;
 
-       numfields = strsplit (buffer, fields, 3);
+       DBG ("option = %s; value = %s;", option, value);
 
-       if ((numfields != 1) && (numfields != 2))
-       {
-               syslog (LOG_ERR, "Invalid number of arguments to `%s'",
-                               shortvar);
-               free (buffer);
-               return (LC_CBRET_ERROR);
-       }
+       for (i = 0; i < cf_global_options_num; i++)
+               if (strcasecmp (cf_global_options[i].key, option) == 0)
+                       break;
 
-       node = fields[0];
-       if (numfields == 2)
-               service = fields[1];
+       if (i >= cf_global_options_num)
+               return (-1);
 
-       /* Still return `LC_CBRET_OKAY' because this is not an syntax error */
-       if (network_create_socket (node, service) < 1)
-               syslog (LOG_ERR, "network_create_socket (%s, %s) failed",
-                               node, service);
+       if (cf_global_options[i].value != NULL)
+               free (cf_global_options[i].value);
 
-       free (buffer);
+       if (value != NULL)
+               cf_global_options[i].value = strdup (value);
+       else
+               cf_global_options[i].value = NULL;
 
-       return (LC_CBRET_OKAY);
+       return (0);
 }
 
-/*
- * `cf_callback_plugin'
- *   Start/end section `plugin'
- *
- * <Plugin `arguments'>
- *   ...
- * </Plugin>
- */
-static int cf_callback_plugin (const char *shortvar, const char *var,
-               const char *arguments, const char *value, lc_flags_t flags,
-               void *extra)
+const char *global_option_get (const char *option)
 {
-       DEBUG_CALLBACK (shortvar, var, arguments, value);
-
-       if (flags == LC_FLAGS_SECTIONSTART)
-       {
-               if (nesting_depth != 0)
-               {
-                       fprintf (stderr, ERR_NOT_NESTED);
-                       return (LC_CBRET_ERROR);
-               }
+       int i;
 
-               if (arguments == NULL)
-               {
-                       fprintf (stderr, ERR_NEEDS_ARG, shortvar);
-                       return (LC_CBRET_ERROR);
-               }
+       for (i = 0; i < cf_global_options_num; i++)
+               if (strcasecmp (cf_global_options[i].key, option) == 0)
+                       break;
 
-               if ((current_module = strdup (arguments)) == NULL)
-               {
-                       perror ("strdup");
-                       return (LC_CBRET_ERROR);
-               }
+       if (i >= cf_global_options_num)
+               return (NULL);
+       
+       return ((cf_global_options[i].value != NULL)
+                       ? cf_global_options[i].value
+                       : cf_global_options[i].def);
+} /* char *global_option_get */
 
-               nesting_depth++;
+void cf_unregister (const char *type)
+{
+       cf_callback_t *this, *prev;
 
-               if (cf_search (current_module) != NULL)
-                       return (LC_CBRET_OKAY);
-               else
-                       return (LC_CBRET_IGNORESECTION);
-       }
-       else if (flags == LC_FLAGS_SECTIONEND)
-       {
-               if (current_module != NULL)
+       for (prev = NULL, this = first_callback;
+                       this != NULL;
+                       prev = this, this = this->next)
+               if (strcasecmp (this->type, type) == 0)
                {
-                       free (current_module);
-                       current_module = NULL;
-               }
-
-               nesting_depth--;
+                       if (prev == NULL)
+                               first_callback = this->next;
+                       else
+                               prev->next = this->next;
 
-               return (LC_CBRET_OKAY);
-       }
-       else
-       {
-               fprintf (stderr, ERR_SECTION_ONLY, shortvar);
-               return (LC_CBRET_ERROR);
-       }
+                       free (this);
+                       break;
+               }
 }
 
-/*
- * `cf_callback_plugin_dispatch'
- *   Send options within `plugin' sections to the plugin that requests it.
- *
- * <Plugin `current_module'>
- *   `var' `value'
- * </Plugin>
- */
-static int cf_callback_plugin_dispatch (const char *shortvar, const char *var,
-               const char *arguments, const char *value, lc_flags_t flags,
-               void *extra)
+void cf_register (const char *type,
+               int (*callback) (const char *, const char *),
+               const char **keys, int keys_num)
 {
-       DEBUG_CALLBACK (shortvar, var, arguments, value);
-
-       if ((nesting_depth == 0) || (current_module == NULL))
-       {
-               fprintf (stderr, ERR_NEEDS_SECTION, shortvar);
-               return (LC_CBRET_ERROR);
-       }
-
-       /* Send the data to the plugin */
-       if (cf_dispatch (current_module, shortvar, value) < 0)
-               return (LC_CBRET_ERROR);
-
-       return (LC_CBRET_OKAY);
-}
+       cf_callback_t *cf_cb;
 
-static void cf_init (void)
-{
-       static int run_once = 0;
-       int i;
+       /* Remove this module from the list, if it already exists */
+       cf_unregister (type);
 
-       if (run_once != 0)
+       /* This pointer will be free'd in `cf_unregister' */
+       if ((cf_cb = (cf_callback_t *) malloc (sizeof (cf_callback_t))) == NULL)
                return;
-       run_once = 1;
-
-       lc_register_callback ("Mode", SHORTOPT_NONE, LC_VAR_STRING,
-                       cf_callback_mode, NULL);
-       lc_register_callback ("Plugin", SHORTOPT_NONE, LC_VAR_SECTION,
-                       cf_callback_plugin, NULL);
-
-       lc_register_callback ("PluginDir", SHORTOPT_NONE,
-                       LC_VAR_STRING, cf_callback_mode_plugindir, NULL);
-       lc_register_callback ("LoadPlugin", SHORTOPT_NONE,
-                       LC_VAR_STRING, cf_callback_mode_loadmodule, NULL);
-
-       lc_register_callback ("Listen", SHORTOPT_NONE,
-                       LC_VAR_STRING, cf_callback_socket, NULL);
-       lc_register_callback ("Server", SHORTOPT_NONE,
-                       LC_VAR_STRING, cf_callback_socket, NULL);
 
-       for (i = 0; i < cf_mode_num; i++)
-       {
-               cf_mode_item_t *item;
-
-               item = &cf_mode_list[i];
+       cf_cb->type     = type;
+       cf_cb->callback = callback;
+       cf_cb->keys     = keys;
+       cf_cb->keys_num = keys_num;
 
-               lc_register_callback (item->key, SHORTOPT_NONE, LC_VAR_STRING,
-                               cf_callback_mode_option, (void *) item);
-       }
-}
+       cf_cb->next = first_callback;
+       first_callback = cf_cb;
+} /* void cf_register */
 
 int cf_read (char *filename)
 {
-       cf_init ();
-
-       if (filename == NULL)
-               filename = CONFIGFILE;
-
-       DBG ("Starting to parse file `%s'", filename);
+       oconfig_item_t *conf;
+       int i;
 
-       /* int lc_process_file(const char *appname, const char *pathname, lc_conf_type_t type); */
-       if (lc_process_file ("collectd", filename, LC_CONF_APACHE))
+       conf = oconfig_parse_file (filename);
+       if (conf == NULL)
        {
-               syslog (LOG_ERR, "lc_process_file (%s): %s", filename, lc_geterrstr ());
+               syslog (LOG_ERR, "Unable to read config file %s.", filename);
                return (-1);
        }
 
-       DBG ("Done parsing file `%s'", filename);
-
-       /* free memory and stuff */
-       lc_cleanup ();
+       for (i = 0; i < conf->children_num; i++)
+       {
+               if (conf->children[i].children == NULL)
+                       dispatch_value (conf->children + i);
+               else
+                       dispatch_block (conf->children + i);
+       }
 
        return (0);
-}
+} /* int cf_read */
index 0bb11b2..0ee8f33 100644 (file)
@@ -31,7 +31,7 @@
  *  `type'      Name of the plugin (must be the same as passed to
  *              `plugin_register'
  */
-void cf_unregister (char *type);
+void cf_unregister (const char *type);
 
 /*
  * DESCRIPTION
@@ -57,24 +57,9 @@ void cf_unregister (char *type);
  *  exists for each `type' at any time. This means that `cf_register' may be
  *  called multiple times, but only the last call will have an effect.
  */
-void cf_register (char *type,
-               int (*callback) (char *, char *),
-               char **keys, int keys_num);
-
-/*
- * DESCRIPTION
- *  `cf_get_option' returns various general options.
- *
- * PARAMETERS
- *  `key'       Name of the option to query.
- *  `def'       Pointer to return as default value.
- *
- * RETURN VALUE
- *  The pointer returned is part of an internal structure and may not be
- *  changed. If the option is not found for whatever reason (wrong key, option
- *  not allowed for currently selected mode, ...) `NULL' is returned.
- */
-char *cf_get_option (const char *key, char *def);
+void cf_register (const char *type,
+               int (*callback) (const char *, const char *),
+               const char **keys, int keys_num);
 
 /*
  * DESCRIPTION
@@ -93,4 +78,7 @@ char *cf_get_option (const char *key, char *def);
  */
 int cf_read (char *filename);
 
+int global_option_set (const char *option, const char *value);
+const char *global_option_get (const char *option);
+
 #endif /* defined(CONFIGFILE_H) */
index b087d66..285841e 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -1,11 +1,10 @@
 /**
  * collectd - src/cpu.c
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,8 +24,6 @@
 #include "plugin.h"
 #include "utils_debug.h"
 
-#define MODULE_NAME "cpu"
-
 #ifdef HAVE_MACH_KERN_RETURN_H
 # include <mach/kern_return.h>
 #endif
 # define CPU_HAVE_READ 0
 #endif
 
+static data_source_t dsrc[1] =
+{
+       {"value", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t ds =
+{
+       "cpu", 1, dsrc
+};
+
+#if CPU_HAVE_READ
 #ifdef PROCESSOR_CPU_LOAD_INFO
 static mach_port_t port_host;
 static processor_port_array_t cpu_list;
@@ -106,20 +114,7 @@ static int numcpu;
 static int numcpu;
 #endif /* HAVE_SYSCTLBYNAME */
 
-static char *cpu_filename = "cpu-%s.rrd";
-
-static char *ds_def[] =
-{
-       "DS:user:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:nice:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:syst:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:idle:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:wait:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       NULL
-};
-static int ds_num = 5;
-
-static void cpu_init (void)
+static int init (void)
 {
 #if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
        kern_return_t status;
@@ -130,13 +125,13 @@ static void cpu_init (void)
        /* FIXME: Free `cpu_list' if it's not NULL */
        if ((status = host_processors (port_host, &cpu_list, &cpu_list_len)) != KERN_SUCCESS)
        {
-               syslog (LOG_ERR, "cpu-plugin: host_processors returned %i\n", (int) status);
+               syslog (LOG_ERR, "cpu plugin: host_processors returned %i", (int) status);
                cpu_list_len = 0;
-               return;
+               return (-1);
        }
 
        DBG ("host_processors returned %i %s", (int) cpu_list_len, cpu_list_len == 1 ? "processor" : "processors");
-       syslog (LOG_INFO, "cpu-plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s");
+       syslog (LOG_INFO, "cpu plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s");
 
        collectd_step = atoi (COLLECTD_STEP);
        if ((collectd_step > 0) && (collectd_step <= 86400))
@@ -150,7 +145,7 @@ static void cpu_init (void)
        numcpu = 0;
 
        if (kc == NULL)
-               return;
+               return (-1);
 
        /* Solaris doesn't count linear.. *sigh* */
        for (numcpu = 0, ksp_chain = kc->kc_chain;
@@ -168,49 +163,37 @@ static void cpu_init (void)
        if (sysctlbyname ("hw.ncpu", &numcpu, &numcpu_size, NULL, 0) < 0)
        {
                syslog (LOG_WARNING, "cpu: sysctlbyname: %s", strerror (errno));
-               return;
+               return (-1);
        }
 
        if (numcpu != 1)
                syslog (LOG_NOTICE, "cpu: Only one processor supported when using `sysctlbyname' (found %i)", numcpu);
 #endif
 
-       return;
-}
+       return (0);
+} /* int init */
 
-static void cpu_write (char *host, char *inst, char *val)
+static void submit (int cpu_num, const char *type_instance, counter_t value)
 {
-       char file[512];
-       int status;
-
-       status = snprintf (file, 512, cpu_filename, inst);
-       if (status < 1)
-               return;
-       else if (status >= 512)
-               return;
-
-       rrd_update_file (host, file, val, ds_def, ds_num);
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].counter = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "cpu");
+       snprintf (vl.plugin_instance, sizeof (vl.type_instance),
+                       "%i", cpu_num);
+       vl.plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
+       strcpy (vl.type_instance, type_instance);
+
+       plugin_dispatch_values ("cpu", &vl);
 }
 
-#if CPU_HAVE_READ
-#define BUFSIZE 512
-static void cpu_submit (int cpu_num, unsigned long long user,
-               unsigned long long nice, unsigned long long syst,
-               unsigned long long idle, unsigned long long wait)
-{
-       char buf[BUFSIZE];
-       char cpu[16];
-
-       if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu", (unsigned int) curtime,
-                               user, nice, syst, idle, wait) >= BUFSIZE)
-               return;
-       snprintf (cpu, 16, "%i", cpu_num);
-
-       plugin_submit (MODULE_NAME, cpu, buf);
-}
-#undef BUFSIZE
-
-static void cpu_read (void)
+static int cpu_read (void)
 {
 #if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
        int cpu;
@@ -238,21 +221,20 @@ static void cpu_read (void)
                                                PROCESSOR_CPU_LOAD_INFO, &cpu_host,
                                                (processor_info_t) &cpu_info, &cpu_info_len)) != KERN_SUCCESS)
                {
-                       syslog (LOG_ERR, "cpu-plugin: processor_info failed with status %i\n", (int) status);
+                       syslog (LOG_ERR, "cpu plugin: processor_info failed with status %i", (int) status);
                        continue;
                }
 
                if (cpu_info_len < CPU_STATE_MAX)
                {
-                       syslog (LOG_ERR, "cpu-plugin: processor_info returned only %i elements..\n", cpu_info_len);
+                       syslog (LOG_ERR, "cpu plugin: processor_info returned only %i elements..", cpu_info_len);
                        continue;
                }
 
-               cpu_submit (cpu, cpu_info.cpu_ticks[CPU_STATE_USER],
-                               cpu_info.cpu_ticks[CPU_STATE_NICE],
-                               cpu_info.cpu_ticks[CPU_STATE_SYSTEM],
-                               cpu_info.cpu_ticks[CPU_STATE_IDLE],
-                               0ULL);
+               submit (cpu, "user", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
+               submit (cpu, "nice", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
+               submit (cpu, "system", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
+               submit (cpu, "idle", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
 #endif /* PROCESSOR_CPU_LOAD_INFO */
 #if PROCESSOR_TEMPERATURE
                /*
@@ -275,7 +257,7 @@ static void cpu_read (void)
                                cpu_temp, &cpu_temp_len);
                if (status != KERN_SUCCESS)
                {
-                       syslog (LOG_ERR, "cpu-plugin: processor_info failed: %s",
+                       syslog (LOG_ERR, "cpu plugin: processor_info failed: %s",
                                        mach_error_string (status));
 
                        cpu_temp_retry_counter = cpu_temp_retry_step;
@@ -302,12 +284,11 @@ static void cpu_read (void)
 /* #endif PROCESSOR_CPU_LOAD_INFO */
 
 #elif defined(KERNEL_LINUX)
-# define BUFSIZE 1024
        int cpu;
-       unsigned long long user, nice, syst, idle;
-       unsigned long long wait, intr, sitr; /* sitr == soft interrupt */
+       counter_t user, nice, syst, idle;
+       counter_t wait, intr, sitr; /* sitr == soft interrupt */
        FILE *fh;
-       char buf[BUFSIZE];
+       char buf[1024];
 
        char *fields[9];
        int numfields;
@@ -319,13 +300,13 @@ static void cpu_read (void)
                plugin_complain (LOG_ERR, &complain_obj, "cpu plugin: "
                                "fopen (/proc/stat) failed: %s",
                                strerror (errno));
-               return;
+               return (-1);
        }
 
        plugin_relief (LOG_NOTICE, &complain_obj, "cpu plugin: "
                        "fopen (/proc/stat) succeeded.");
 
-       while (fgets (buf, BUFSIZE, fh) != NULL)
+       while (fgets (buf, 1024, fh) != NULL)
        {
                if (strncmp (buf, "cpu", 3))
                        continue;
@@ -342,31 +323,29 @@ static void cpu_read (void)
                syst = atoll (fields[3]);
                idle = atoll (fields[4]);
 
+               submit (cpu, "user", user);
+               submit (cpu, "nice", nice);
+               submit (cpu, "system", syst);
+               submit (cpu, "idle", idle);
+
                if (numfields >= 8)
                {
                        wait = atoll (fields[5]);
                        intr = atoll (fields[6]);
                        sitr = atoll (fields[7]);
 
-                       /* I doubt anyone cares about the time spent in
-                        * interrupt handlers.. */
-                       syst += intr + sitr;
-               }
-               else
-               {
-                       wait = 0LL;
+                       submit (cpu, "wait", wait);
+                       submit (cpu, "interrupt", intr);
+                       submit (cpu, "softirq", sitr);
                }
-
-               cpu_submit (cpu, user, nice, syst, idle, wait);
        }
 
        fclose (fh);
-#undef BUFSIZE
 /* #endif defined(KERNEL_LINUX) */
 
 #elif defined(HAVE_LIBKSTAT)
        int cpu;
-       unsigned long long user, syst, idle, wait;
+       counter_t user, syst, idle, wait;
        static cpu_stat_t cs;
 
        if (kc == NULL)
@@ -377,13 +356,15 @@ static void cpu_read (void)
                if (kstat_read (kc, ksp[cpu], &cs) == -1)
                        continue; /* error message? */
 
-               idle = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_IDLE];
-               user = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_USER];
-               syst = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_KERNEL];
-               wait = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_WAIT];
+               idle = (counter_t) cs.cpu_sysinfo.cpu[CPU_IDLE];
+               user = (counter_t) cs.cpu_sysinfo.cpu[CPU_USER];
+               syst = (counter_t) cs.cpu_sysinfo.cpu[CPU_KERNEL];
+               wait = (counter_t) cs.cpu_sysinfo.cpu[CPU_WAIT];
 
-               cpu_submit (ksp[cpu]->ks_instance,
-                               user, 0LL, syst, idle, wait);
+               submit (ksp[cpu]->ks_instance, "user", user);
+               submit (ksp[cpu]->ks_instance, "system", syst);
+               submit (ksp[cpu]->ks_instance, "idle", idle);
+               submit (ksp[cpu]->ks_instance, "wait", wait);
        }
 /* #endif defined(HAVE_LIBKSTAT) */
 
@@ -408,19 +389,22 @@ static void cpu_read (void)
 
        cpuinfo[CP_SYS] += cpuinfo[CP_INTR];
 
-       /* FIXME: Instance is always `0' */
-       cpu_submit (0, cpuinfo[CP_USER], cpuinfo[CP_NICE], cpuinfo[CP_SYS], cpuinfo[CP_IDLE], 0LL);
+       submit (0, "user", cpuinfo[CP_USER]);
+       submit (0, "nice", cpuinfo[CP_NICE]);
+       submit (0, "system", cpuinfo[CP_SYS]);
+       submit (0, "idle", cpuinfo[CP_IDLE]);
 #endif
 
-       return;
+       return (0);
 }
-#else
-# define cpu_read NULL
 #endif /* CPU_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, cpu_init, cpu_read, cpu_write);
-}
+       plugin_register_data_set (&ds);
 
-#undef MODULE_NAME
+#if CPU_HAVE_READ
+       plugin_register_init ("cpu", init);
+       plugin_register_read ("cpu", cpu_read);
+#endif /* CPU_HAVE_READ */
+}
index ba0149a..008ef39 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/cpufreq.c
- * Copyright (C) 2005,2006  Peter Holik
+ * Copyright (C) 2005-2007  Peter Holik
  *
  * 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
 # define CPUFREQ_HAVE_READ 0
 #endif
 
-static char *cpufreq_file = "cpufreq-%s.rrd";
+static data_source_t data_source[1] =
+{
+       {"value", DS_TYPE_GAUGE, 0, NAN}
+};
 
-static char *ds_def[] =
+static data_set_t data_set =
 {
-       "DS:value:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       "cpufreq", 1, data_source
 };
-static int ds_num = 1;
 
+#if CPUFREQ_HAVE_READ
 #ifdef KERNEL_LINUX
 static int num_cpu = 0;
 #endif
 
-#define BUFSIZE 256
-
-static void cpufreq_init (void)
+static int cpufreq_init (void)
 {
 #ifdef KERNEL_LINUX
         int status;
-       char filename[BUFSIZE];
+       char filename[256];
 
        num_cpu = 0;
 
        while (1)
        {
-               status = snprintf (filename, BUFSIZE, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", num_cpu);
-               if (status < 1 || status >= BUFSIZE)
+               status = snprintf (filename, sizeof (filename),
+                               "/sys/devices/system/cpu/cpu%d/cpufreq/"
+                               "scaling_cur_freq", num_cpu);
+               if (status < 1 || status >= sizeof (filename))
                        break;
 
-               if (access(filename, R_OK))
+               if (access (filename, R_OK))
                        break;
 
                num_cpu++;
        }
 
-       syslog (LOG_INFO, MODULE_NAME" found %d cpu(s)", num_cpu);
+       syslog (LOG_INFO, "cpufreq plugin: Found %d CPU%s", num_cpu,
+                       (num_cpu == 1) ? "" : "s");
+
+       if (num_cpu == 0)
+               plugin_unregister_read ("cpufreq");
 #endif /* defined(KERNEL_LINUX) */
 
-       return;
-}
+       return (0);
+} /* int cpufreq_init */
 
-static void cpufreq_write (char *host, char *inst, char *val)
+static void cpufreq_submit (int cpu_num, double value)
 {
-        int status;
-        char file[BUFSIZE];
-
-        status = snprintf (file, BUFSIZE, cpufreq_file, inst);
-        if (status < 1 || status >= BUFSIZE)
-                return;
-
-       rrd_update_file (host, file, val, ds_def, ds_num);
-}
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-#if CPUFREQ_HAVE_READ
-static void cpufreq_submit (int cpu_num, unsigned long long val)
-{
-       char buf[BUFSIZE];
-       char cpu[16];
+       values[0].gauge = value;
 
-       if (snprintf (buf, BUFSIZE, "%u:%llu", (unsigned int) curtime, val) >= BUFSIZE)
-               return;
-        snprintf (cpu, 16, "%i", cpu_num);
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "cpufreq");
+       snprintf (vl.type_instance, sizeof (vl.type_instance),
+                       "%i", cpu_num);
 
-       plugin_submit (MODULE_NAME, cpu, buf);
+       plugin_dispatch_values ("cpufreq", &vl);
 }
 
-static void cpufreq_read (void)
+static int cpufreq_read (void)
 {
 #ifdef KERNEL_LINUX
         int status;
        unsigned long long val;
        int i = 0;
        FILE *fp;
-       char filename[BUFSIZE];
+       char filename[256];
        char buffer[16];
 
        for (i = 0; i < num_cpu; i++)
        {
-               status = snprintf (filename, BUFSIZE, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i);
-               if (status < 1 || status >= BUFSIZE)
-                       return;
+               status = snprintf (filename, sizeof (filename),
+                               "/sys/devices/system/cpu/cpu%d/cpufreq/"
+                               "scaling_cur_freq", i);
+               if (status < 1 || status >= sizeof (filename))
+                       return (-1);
 
                if ((fp = fopen (filename, "r")) == NULL)
                {
                        syslog (LOG_WARNING, "cpufreq: fopen: %s", strerror (errno));
-                       return;
+                       return (-1);
                }
 
                if (fgets (buffer, 16, fp) == NULL)
                {
                        syslog (LOG_WARNING, "cpufreq: fgets: %s", strerror (errno));
                        fclose (fp);
-                       return;
+                       return (-1);
                }
 
                if (fclose (fp))
@@ -137,16 +138,17 @@ static void cpufreq_read (void)
        }
 #endif /* defined(KERNEL_LINUX) */
 
-       return;
-}
-#else
-#define cpufreq_read NULL
-#endif
+       return (0);
+} /* int cpufreq_read */
+#endif /* CPUFREQ_HAVE_READ */
 #undef BUFSIZE
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, cpufreq_init, cpufreq_read, cpufreq_write);
-}
+       plugin_register_data_set (&data_set);
 
-#undef MODULE_NAME
+#if CPUFREQ_HAVE_READ
+       plugin_register_init ("cpufreq", cpufreq_init);
+       plugin_register_read ("cpufreq", cpufreq_read);
+#endif /* CPUFREQ_HAVE_READ */
+}
diff --git a/src/csv.c b/src/csv.c
new file mode 100644 (file)
index 0000000..f4b56fe
--- /dev/null
+++ b/src/csv.c
@@ -0,0 +1,268 @@
+/**
+ * collectd - src/csv.c
+ * Copyright (C) 2007  Florian octo Forster
+ *
+ * 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; only version 2 of the License is applicable.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_debug.h"
+
+/*
+ * Private variables
+ */
+static const char *config_keys[] =
+{
+       "DataDir"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static char *datadir   = NULL;
+
+static int value_list_to_string (char *buffer, int buffer_len,
+               const data_set_t *ds, const value_list_t *vl)
+{
+       int offset;
+       int status;
+       int i;
+
+       memset (buffer, '\0', sizeof (buffer_len));
+
+       status = snprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
+       if ((status < 1) || (status >= buffer_len))
+               return (-1);
+       offset = status;
+
+       for (i = 0; i < ds->ds_num; i++)
+       {
+               if ((ds->ds[i].type != DS_TYPE_COUNTER)
+                               && (ds->ds[i].type != DS_TYPE_GAUGE))
+                       return (-1);
+
+               if (ds->ds[i].type == DS_TYPE_COUNTER)
+                       status = snprintf (buffer + offset, buffer_len - offset,
+                                       ",%llu", vl->values[i].counter);
+               else
+                       status = snprintf (buffer + offset, buffer_len - offset,
+                                       ",%lf", vl->values[i].gauge);
+
+               if ((status < 1) || (status >= (buffer_len - offset)))
+                       return (-1);
+
+               offset += status;
+       } /* for ds->ds_num */
+
+       return (0);
+} /* int value_list_to_string */
+
+static int value_list_to_filename (char *buffer, int buffer_len,
+               const data_set_t *ds, const value_list_t *vl)
+{
+       int offset = 0;
+       int status;
+
+       if (datadir != NULL)
+       {
+               status = snprintf (buffer + offset, buffer_len - offset,
+                               "%s/", datadir);
+               if ((status < 1) || (status >= buffer_len - offset))
+                       return (-1);
+               offset += status;
+       }
+
+       status = snprintf (buffer + offset, buffer_len - offset,
+                       "%s/", vl->host);
+       if ((status < 1) || (status >= buffer_len - offset))
+               return (-1);
+       offset += status;
+
+       if (strlen (vl->plugin_instance) > 0)
+               status = snprintf (buffer + offset, buffer_len - offset,
+                               "%s-%s/", vl->plugin, vl->plugin_instance);
+       else
+               status = snprintf (buffer + offset, buffer_len - offset,
+                               "%s/", vl->plugin);
+       if ((status < 1) || (status >= buffer_len - offset))
+               return (-1);
+       offset += status;
+
+       if (strlen (vl->type_instance) > 0)
+               status = snprintf (buffer + offset, buffer_len - offset,
+                               "%s-%s", ds->type, vl->type_instance);
+       else
+               status = snprintf (buffer + offset, buffer_len - offset,
+                               "%s", ds->type);
+       if ((status < 1) || (status >= buffer_len - offset))
+               return (-1);
+       offset += status;
+
+       {
+               time_t now;
+               struct tm stm;
+
+               /* TODO: Find a way to minimize the calls to `localtime_r',
+                * since they are pretty expensive.. */
+               now = time (NULL);
+               if (localtime_r (&now, &stm) == NULL)
+               {
+                       syslog (LOG_ERR, "csv plugin: localtime_r failed");
+                       return (1);
+               }
+
+               strftime (buffer + offset, buffer_len - offset,
+                               "-%Y-%m-%d", &stm);
+       }
+
+       return (0);
+} /* int value_list_to_filename */
+
+static int csv_create_file (const char *filename, const data_set_t *ds)
+{
+       FILE *csv;
+       int i;
+
+       if (check_create_dir (filename))
+               return (-1);
+
+       csv = fopen (filename, "w");
+       if (csv == NULL)
+       {
+               syslog (LOG_ERR, "csv plugin: fopen (%s) failed: %s",
+                               filename, strerror(errno));
+               return (-1);
+       }
+
+       fprintf (csv, "epoch");
+       for (i = 0; i < ds->ds_num; i++)
+               fprintf (csv, ",%s", ds->ds[i].name);
+
+       fprintf (csv, "\n");
+       fclose (csv);
+
+       return 0;
+} /* int csv_create_file */
+
+static int csv_config (const char *key, const char *value)
+{
+       if (strcasecmp ("DataDir", key) == 0)
+       {
+               if (datadir != NULL)
+                       free (datadir);
+               datadir = strdup (value);
+               if (datadir != NULL)
+               {
+                       int len = strlen (datadir);
+                       while ((len > 0) && (datadir[len - 1] == '/'))
+                       {
+                               len--;
+                               datadir[len] = '\0';
+                       }
+                       if (len <= 0)
+                       {
+                               free (datadir);
+                               datadir = NULL;
+                       }
+               }
+       }
+       else
+       {
+               return (-1);
+       }
+       return (0);
+} /* int csv_config */
+
+static int csv_write (const data_set_t *ds, const value_list_t *vl)
+{
+       struct stat  statbuf;
+       char         filename[512];
+       char         values[512];
+       FILE        *csv;
+       int          csv_fd;
+       struct flock fl;
+       int          status;
+
+       if (value_list_to_filename (filename, sizeof (filename), ds, vl) != 0)
+               return (-1);
+
+       DBG ("filename = %s;", filename);
+
+       if (value_list_to_string (values, sizeof (values), ds, vl) != 0)
+               return (-1);
+
+       if (stat (filename, &statbuf) == -1)
+       {
+               if (errno == ENOENT)
+               {
+                       if (csv_create_file (filename, ds))
+                               return (-1);
+               }
+               else
+               {
+                       syslog (LOG_ERR, "stat(%s) failed: %s",
+                                       filename, strerror (errno));
+                       return (-1);
+               }
+       }
+       else if (!S_ISREG (statbuf.st_mode))
+       {
+               syslog (LOG_ERR, "stat(%s): Not a regular file!",
+                               filename);
+               return (-1);
+       }
+
+       csv = fopen (filename, "a");
+       if (csv == NULL)
+       {
+               syslog (LOG_ERR, "csv plugin: fopen (%s) failed: %s",
+                               filename, strerror (errno));
+               return (-1);
+       }
+       csv_fd = fileno (csv);
+
+       memset (&fl, '\0', sizeof (fl));
+       fl.l_start  = 0;
+       fl.l_len    = 0; /* till end of file */
+       fl.l_pid    = getpid ();
+       fl.l_type   = F_WRLCK;
+       fl.l_whence = SEEK_SET;
+
+       status = fcntl (csv_fd, F_SETLK, &fl);
+       if (status != 0)
+       {
+               syslog (LOG_ERR, "csv plugin: flock (%s) failed: %s",
+                               filename, strerror (errno));
+               fclose (csv);
+               return (-1);
+       }
+
+       fprintf (csv, "%s\n", values);
+
+       /* The lock is implicitely released. I we don't release it explicitely
+        * because the `FILE *' may need to flush a cache first */
+       fclose (csv);
+
+       return (0);
+} /* int csv_write */
+
+void module_register (void)
+{
+       plugin_register_config ("csv", csv_config,
+                       config_keys, config_keys_num);
+       plugin_register_write ("csv", csv_write);
+}
index d327164..fde5d9a 100644 (file)
--- a/src/df.c
+++ b/src/df.c
@@ -1,11 +1,10 @@
 /**
  * collectd - src/df.c
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,8 +26,6 @@
 #include "utils_mount.h"
 #include "utils_ignorelist.h"
 
-#define MODULE_NAME "df"
-
 #if HAVE_STATFS || HAVE_STATVFS
 # define DF_HAVE_READ 1
 #else
 # define BLOCKSIZE(s) (s).f_bsize
 #endif
 
-static char *filename_template = "df-%s.rrd";
+/* 2^50 - 1 == 1125899906842623 = 1 Petabyte */
+static data_source_t dsrc[2] =
+{
+       {"free", DS_TYPE_GAUGE, 0, 1125899906842623.0},
+       {"used", DS_TYPE_GAUGE, 0, 1125899906842623.0}
+};
 
-static char *ds_def[] =
+static data_set_t ds =
 {
-       "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       "df", 2, dsrc
 };
-static int ds_num = 2;
 
-static char *config_keys[] =
+#if DF_HAVE_READ
+static const char *config_keys[] =
 {
        "Device",
        "MountPoint",
@@ -73,9 +73,7 @@ static ignorelist_t *il_device = NULL;
 static ignorelist_t *il_mountpoint = NULL;
 static ignorelist_t *il_fstype = NULL;
 
-#define BUFSIZE 512
-
-static void df_init (void)
+static int df_init (void)
 {
        if (il_device == NULL)
                il_device = ignorelist_create (1);
@@ -84,10 +82,10 @@ static void df_init (void)
        if (il_fstype == NULL)
                il_fstype = ignorelist_create (1);
 
-       return;
+       return (0);
 }
 
-static int df_config (char *key, char *value)
+static int df_config (const char *key, const char *value)
 {
        df_init ();
 
@@ -131,35 +129,28 @@ static int df_config (char *key, char *value)
        return (-1);
 }
 
-static void df_write (char *host, char *inst, char *val)
-{
-       char file[BUFSIZE];
-       int status;
-
-       status = snprintf (file, BUFSIZE, filename_template, inst);
-       if (status < 1)
-               return;
-       else if (status >= BUFSIZE)
-               return;
-
-       rrd_update_file (host, file, val, ds_def, ds_num);
-}
-
-#if DF_HAVE_READ
 static void df_submit (char *df_name,
-               unsigned long long df_used,
-               unsigned long long df_free)
+               gauge_t df_used,
+               gauge_t df_free)
 {
-       char buf[BUFSIZE];
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       if (snprintf (buf, BUFSIZE, "%u:%llu:%llu", (unsigned int) curtime,
-                               df_used, df_free) >= BUFSIZE)
-               return;
+       values[0].gauge = df_used;
+       values[1].gauge = df_free;
 
-       plugin_submit (MODULE_NAME, df_name, buf);
-}
+       vl.values = values;
+       vl.values_len = 2;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "df");
+       strcpy (vl.plugin_instance, "");
+       strncpy (vl.type_instance, df_name, sizeof (vl.type_instance));
 
-static void df_read (void)
+       plugin_dispatch_values ("df", &vl);
+} /* void df_submit */
+
+static int df_read (void)
 {
 #if HAVE_STATVFS
        struct statvfs statbuf;
@@ -171,13 +162,13 @@ static void df_read (void)
        cu_mount_t *mnt_ptr;
 
        unsigned long long blocksize;
-       unsigned long long df_free;
-       unsigned long long df_used;
-       char mnt_name[BUFSIZE];
+       gauge_t df_free;
+       gauge_t df_used;
+       char mnt_name[256];
 
        mnt_list = NULL;
        if (cu_mount_getlist (&mnt_list) == NULL)
-               return;
+               return (-1);
 
        for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
        {
@@ -196,13 +187,13 @@ static void df_read (void)
 
                if (strcmp (mnt_ptr->dir, "/") == 0)
                {
-                       strncpy (mnt_name, "root", BUFSIZE);
+                       strncpy (mnt_name, "root", sizeof (mnt_name));
                }
                else
                {
                        int i, len;
 
-                       strncpy (mnt_name, mnt_ptr->dir + 1, BUFSIZE);
+                       strncpy (mnt_name, mnt_ptr->dir + 1, sizeof (mnt_name));
                        len = strlen (mnt_name);
 
                        for (i = 0; i < len; i++)
@@ -224,16 +215,18 @@ static void df_read (void)
        }
 
        cu_mount_freelist (mnt_list);
-} /* static void df_read (void) */
-#else
-# define df_read NULL
+
+       return (0);
+} /* int df_read */
 #endif /* DF_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, df_init, df_read, df_write);
-       cf_register (MODULE_NAME, df_config, config_keys, config_keys_num);
-}
+       plugin_register_data_set (&ds);
 
-#undef BUFSIZE
-#undef MODULE_NAME
+#if DF_HAVE_READ
+       plugin_register_config ("df", df_config, config_keys, config_keys_num);
+       plugin_register_init ("df", df_init);
+       plugin_register_read ("df", df_read);
+#endif
+} /* void module_register */
index c809fdb..af7c01a 100644 (file)
@@ -1,11 +1,10 @@
 /**
  * collectd - src/disk.c
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,8 +24,6 @@
 #include "plugin.h"
 #include "utils_debug.h"
 
-#define MODULE_NAME "disk"
-
 #if HAVE_MACH_MACH_TYPES_H
 #  include <mach/mach_types.h>
 #endif
 # define DISK_HAVE_READ 0
 #endif
 
-static char *disk_filename_template = "disk-%s.rrd";
-static char *part_filename_template = "partition-%s.rrd";
+/* 2^34 = 17179869184 = ~17.2GByte/s */
+static data_source_t octets_dsrc[2] =
+{
+       {"read",  DS_TYPE_COUNTER, 0, 17179869183.0},
+       {"write", DS_TYPE_COUNTER, 0, 17179869183.0}
+};
+
+static data_set_t octets_ds =
+{
+       "disk_octets", 2, octets_dsrc
+};
+
+static data_source_t operations_dsrc[2] =
+{
+       {"read",  DS_TYPE_COUNTER, 0, 4294967295.0},
+       {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
 
-/* 104857600 == 100 MB */
-static char *disk_ds_def[] =
+static data_set_t operations_ds =
 {
-       "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:rmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
-       "DS:rtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:wmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
-       "DS:wtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       "disk_ops", 2, operations_dsrc
 };
-static int disk_ds_num = 8;
 
-static char *part_ds_def[] =
+static data_source_t merged_dsrc[2] =
 {
-       "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
-       "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
-       NULL
+       {"read",  DS_TYPE_COUNTER, 0, 4294967295.0},
+       {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
 };
-static int part_ds_num = 4;
 
+static data_set_t merged_ds =
+{
+       "disk_merged", 2, merged_dsrc
+};
+
+/* max is 1000000us per second. */
+static data_source_t time_dsrc[2] =
+{
+       {"read",  DS_TYPE_COUNTER, 0, 1000000.0},
+       {"write", DS_TYPE_COUNTER, 0, 1000000.0}
+};
+
+static data_set_t time_ds =
+{
+       "disk_time", 2, time_dsrc
+};
+
+#if DISK_HAVE_READ
 #if HAVE_IOKIT_IOKITLIB_H
 static mach_port_t io_master_port = MACH_PORT_NULL;
 /* #endif HAVE_IOKIT_IOKITLIB_H */
@@ -101,11 +117,11 @@ typedef struct diskstats
        /* This overflows in roughly 1361 year */
        unsigned int poll_count;
 
-       unsigned long long read_sectors;
-       unsigned long long write_sectors;
+       counter_t read_sectors;
+       counter_t write_sectors;
 
-       unsigned long long read_bytes;
-       unsigned long long write_bytes;
+       counter_t read_bytes;
+       counter_t write_bytes;
 
        struct diskstats *next;
 } diskstats_t;
@@ -121,7 +137,7 @@ static kstat_t *ksp[MAX_NUMDISK];
 static int numdisk = 0;
 #endif /* HAVE_LIBKSTAT */
 
-static void disk_init (void)
+static int disk_init (void)
 {
 #if HAVE_IOKIT_IOKITLIB_H
        kern_return_t status;
@@ -139,7 +155,7 @@ static void disk_init (void)
                syslog (LOG_ERR, "IOMasterPort failed: %s",
                                mach_error_string (status));
                io_master_port = MACH_PORT_NULL;
-               return;
+               return (-1);
        }
 /* #endif HAVE_IOKIT_IOKITLIB_H */
 
@@ -163,7 +179,7 @@ static void disk_init (void)
        numdisk = 0;
 
        if (kc == NULL)
-               return;
+               return (-1);
 
        for (numdisk = 0, ksp_chain = kc->kc_chain;
                        (numdisk < MAX_NUMDISK) && (ksp_chain != NULL);
@@ -178,83 +194,29 @@ static void disk_init (void)
        }
 #endif /* HAVE_LIBKSTAT */
 
-       return;
-}
+       return (0);
+} /* int disk_init */
 
-static void disk_write (char *host, char *inst, char *val)
+static void disk_submit (const char *plugin_instance,
+               const char *type,
+               counter_t read, counter_t write)
 {
-       char file[512];
-       int status;
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       status = snprintf (file, 512, disk_filename_template, inst);
-       if (status < 1)
-               return;
-       else if (status >= 512)
-               return;
+       values[0].counter = read;
+       values[1].counter = write;
 
-       rrd_update_file (host, file, val, disk_ds_def, disk_ds_num);
-}
+       vl.values = values;
+       vl.values_len = 2;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "disk");
+       strncpy (vl.plugin_instance, plugin_instance,
+                       sizeof (vl.plugin_instance));
 
-static void partition_write (char *host, char *inst, char *val)
-{
-       char file[512];
-       int status;
-
-       status = snprintf (file, 512, part_filename_template, inst);
-       if (status < 1)
-               return;
-       else if (status >= 512)
-               return;
-
-       rrd_update_file (host, file, val, part_ds_def, part_ds_num);
-}
-
-#if DISK_HAVE_READ
-#define BUFSIZE 512
-static void disk_submit (char *disk_name,
-               unsigned long long read_count,
-               unsigned long long read_merged,
-               unsigned long long read_bytes,
-               unsigned long long read_time,
-               unsigned long long write_count,
-               unsigned long long write_merged,
-               unsigned long long write_bytes,
-               unsigned long long write_time)
-{
-       char buf[BUFSIZE];
-
-       if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
-                               (unsigned int) curtime,
-                               read_count, read_merged, read_bytes, read_time,
-                               write_count, write_merged, write_bytes,
-                               write_time) >= BUFSIZE)
-               return;
-
-       DBG ("disk_name = %s; buf = %s;",
-                       disk_name, buf);
-
-       plugin_submit (MODULE_NAME, disk_name, buf);
-}
-
-#if KERNEL_LINUX || HAVE_LIBKSTAT
-static void partition_submit (char *part_name,
-               unsigned long long read_count,
-               unsigned long long read_bytes,
-               unsigned long long write_count,
-               unsigned long long write_bytes)
-{
-       char buf[BUFSIZE];
-
-       if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu",
-                               (unsigned int) curtime,
-                               read_count, read_bytes, write_count,
-                               write_bytes) >= BUFSIZE)
-               return;
-
-       plugin_submit ("partition", part_name, buf);
-}
-#endif /* KERNEL_LINUX || HAVE_LIBKSTAT */
-#undef BUFSIZE
+       plugin_dispatch_values (type, &vl);
+} /* void disk_submit */
 
 #if HAVE_IOKIT_IOKITLIB_H
 static signed long long dict_get_value (CFDictionaryRef dict, const char *key)
@@ -293,7 +255,7 @@ static signed long long dict_get_value (CFDictionaryRef dict, const char *key)
 }
 #endif /* HAVE_IOKIT_IOKITLIB_H */
 
-static void disk_read (void)
+static int disk_read (void)
 {
 #if HAVE_IOKIT_IOKITLIB_H
        io_registry_entry_t     disk;
@@ -324,7 +286,7 @@ static void disk_read (void)
        {
                plugin_complain (LOG_ERR, &complain_obj, "disk plugin: "
                                "IOServiceGetMatchingServices failed.");
-               return;
+               return (-1);
        }
        else if (complain_obj.interval != 0)
        {
@@ -395,6 +357,7 @@ static void disk_read (void)
                        continue;
                }
 
+               /* kIOBSDNameKey */
                disk_major = (int) dict_get_value (child_dict,
                                kIOBSDMajorKey);
                disk_minor = (int) dict_get_value (child_dict,
@@ -409,6 +372,11 @@ static void disk_read (void)
                                kIOBlockStorageDriverStatisticsWritesKey);
                write_byt = dict_get_value (stats_dict,
                                kIOBlockStorageDriverStatisticsBytesWrittenKey);
+               /* This property describes the number of nanoseconds spent
+                * performing writes since the block storage driver was
+                * instantiated. It is one of the statistic entries listed
+                * under the top-level kIOBlockStorageDriverStatisticsKey
+                * property table. It has an OSNumber value. */
                write_tme = dict_get_value (stats_dict,
                                kIOBlockStorageDriverStatisticsTotalWriteTimeKey);
 
@@ -423,15 +391,14 @@ static void disk_read (void)
                }
                DBG ("disk_name = %s", disk_name);
 
-               if ((read_ops != -1LL)
-                               || (read_byt != -1LL)
-                               || (read_tme != -1LL)
-                               || (write_ops != -1LL)
-                               || (write_byt != -1LL)
-                               || (write_tme != -1LL))
-                       disk_submit (disk_name,
-                                       read_ops, 0ULL, read_byt, read_tme,
-                                       write_ops, 0ULL, write_byt, write_tme);
+               if ((read_byt != -1LL) || (write_byt != -1LL))
+                       disk_submit (disk_name, "disk_octets", read_byt, write_byt);
+               if ((read_ops != -1LL) || (write_ops != -1LL))
+                       disk_submit (disk_name, "disk_ops", read_ops, write_ops);
+               if ((read_tme != -1LL) || (write_tme != -1LL))
+                       disk_submit (disk_name, "disk_time",
+                                       read_tme / 1000,
+                                       write_tme / 1000);
 
                CFRelease (child_dict);
                IOObjectRelease (disk_child);
@@ -444,7 +411,6 @@ static void disk_read (void)
 #elif KERNEL_LINUX
        FILE *fh;
        char buffer[1024];
-       char disk_name[128];
        
        char *fields[32];
        int numfields;
@@ -453,17 +419,17 @@ static void disk_read (void)
        int major = 0;
        int minor = 0;
 
-       unsigned long long read_sectors  = 0ULL;
-       unsigned long long write_sectors = 0ULL;
-
-       unsigned long long read_count    = 0ULL;
-       unsigned long long read_merged   = 0ULL;
-       unsigned long long read_bytes    = 0ULL;
-       unsigned long long read_time     = 0ULL;
-       unsigned long long write_count   = 0ULL;
-       unsigned long long write_merged  = 0ULL;
-       unsigned long long write_bytes   = 0ULL;
-       unsigned long long write_time    = 0ULL;
+       counter_t read_sectors  = 0;
+       counter_t write_sectors = 0;
+
+       counter_t read_count    = 0;
+       counter_t read_merged   = 0;
+       counter_t read_bytes    = 0;
+       counter_t read_time     = 0;
+       counter_t write_count   = 0;
+       counter_t write_merged  = 0;
+       counter_t write_bytes   = 0;
+       counter_t write_time    = 0;
        int is_disk = 0;
 
        diskstats_t *ds, *pre_ds;
@@ -474,18 +440,23 @@ static void disk_read (void)
        {
                if ((fh = fopen ("/proc/partitions", "r")) == NULL)
                {
-                       plugin_complain (LOG_ERR, &complain_obj, "disk plugin: Failed to open /proc/{diskstats,partitions}.");
-                       return;
+                       plugin_complain (LOG_ERR, &complain_obj,
+                                       "disk plugin: Failed to open /proc/"
+                                       "{diskstats,partitions}.");
+                       return (-1);
                }
 
                /* Kernel is 2.4.* */
                fieldshift = 1;
        }
 
-       plugin_relief (LOG_NOTICE, &complain_obj, "disk plugin: Succeeded to open /proc/{diskstats,partitions}.");
+       plugin_relief (LOG_NOTICE, &complain_obj, "disk plugin: "
+                       "Succeeded to open /proc/{diskstats,partitions}.");
 
-       while (fgets (buffer, 1024, fh) != NULL)
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
        {
+               char *disk_name;
+
                numfields = strsplit (buffer, fields, 32);
 
                if ((numfields != (14 + fieldshift)) && (numfields != 7))
@@ -494,9 +465,7 @@ static void disk_read (void)
                major = atoll (fields[0]);
                minor = atoll (fields[1]);
 
-               if (snprintf (disk_name, 128, "%i-%i", major, minor) < 1)
-                       continue;
-               disk_name[127] = '\0';
+               disk_name = fields[2];
 
                for (ds = disklist, pre_ds = disklist; ds != NULL; pre_ds = ds, ds = ds->next)
                        if (strcmp (disk_name, ds->name) == 0)
@@ -582,12 +551,21 @@ static void disk_read (void)
                        continue;
                }
 
+               if ((read_bytes != -1LL) || (write_bytes != -1LL))
+                       disk_submit (disk_name, "disk_octets", read_bytes, write_bytes);
+               if ((read_count != -1LL) || (write_count != -1LL))
+                       disk_submit (disk_name, "disk_ops", read_count, write_count);
                if (is_disk)
-                       disk_submit (disk_name, read_count, read_merged, read_bytes, read_time,
-                                       write_count, write_merged, write_bytes, write_time);
-               else
-                       partition_submit (disk_name, read_count, read_bytes, write_count, write_bytes);
-       }
+               {
+                       if ((read_merged != -1LL) || (write_merged != -1LL))
+                               disk_submit (disk_name, "disk_merged",
+                                               read_merged, write_merged);
+                       if ((read_time != -1LL) || (write_time != -1LL))
+                               disk_submit (disk_name, "disk_time",
+                                               read_time * 1000,
+                                               write_time * 1000);
+               }
+       } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
 
        fclose (fh);
 /* #endif defined(KERNEL_LINUX) */
@@ -597,7 +575,7 @@ static void disk_read (void)
        int i;
 
        if (kc == NULL)
-               return;
+               return (-1);
 
        for (i = 0; i < numdisk; i++)
        {
@@ -605,24 +583,33 @@ static void disk_read (void)
                        continue;
 
                if (strncmp (ksp[i]->ks_class, "disk", 4) == 0)
-                       disk_submit (ksp[i]->ks_name,
-                                       kio.reads,  0LL, kio.nread,    kio.rtime,
-                                       kio.writes, 0LL, kio.nwritten, kio.wtime);
+               {
+                       disk_submit (ksp[i]->ks_name, "disk_octets", kio.reads, kio.writes);
+                       disk_submit (ksp[i]->ks_name, "disk_ops", kio.nreads, kio.nwrites);
+                       /* FIXME: Convert this to microseconds if necessary */
+                       disk_submit (ksp[i]->ks_name, "disk_time", kio.rtime, kio.wtime);
+               }
                else if (strncmp (ksp[i]->ks_class, "partition", 9) == 0)
-                       partition_submit (ksp[i]->ks_name,
-                                       kio.reads, kio.nread,
-                                       kio.writes,kio.nwritten);
+               {
+                       disk_submit (ksp[i]->ks_name, "disk_octets", kio.reads, kio.writes);
+                       disk_submit (ksp[i]->ks_name, "disk_ops", kio.nreads, kio.nwrites);
+               }
        }
 #endif /* defined(HAVE_LIBKSTAT) */
-} /* static void disk_read (void) */
-#else
-# define disk_read NULL
+
+       return (0);
+} /* int disk_read */
 #endif /* DISK_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register ("partition", NULL, NULL, partition_write);
-       plugin_register (MODULE_NAME, disk_init, disk_read, disk_write);
-}
+       plugin_register_data_set (&octets_ds);
+       plugin_register_data_set (&operations_ds);
+       plugin_register_data_set (&merged_ds);
+       plugin_register_data_set (&time_ds);
 
-#undef MODULE_NAME
+#if DISK_HAVE_READ
+       plugin_register_init ("disk", disk_init);
+       plugin_register_read ("disk", disk_read);
+#endif /* DISK_HAVE_READ */
+}
index cd73a7e..56df184 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -1,11 +1,10 @@
 /**
  * collectd - src/dns.c
- * Copyright (C) 2006  Florian octo Forster
+ * Copyright (C) 2006,2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 #include "configfile.h"
 #include "utils_debug.h"
 
-#define MODULE_NAME "dns"
-
 #if HAVE_LIBPCAP && HAVE_LIBPTHREAD
 # include "utils_dns.h"
 # include <pthread.h>
 # include <pcap.h>
-# include <sys/poll.h>
+# include <poll.h>
 # define DNS_HAVE_READ 1
 #else
 # define DNS_HAVE_READ 0
@@ -54,43 +51,39 @@ typedef struct counter_list_s counter_list_t;
 /*
  * Private variables
  */
-static char *traffic_file   = "dns/dns_traffic.rrd";
-static char *qtype_file   = "dns/qtype-%s.rrd";
-static char *opcode_file  = "dns/opcode-%s.rrd";
-static char *rcode_file   = "dns/rcode-%s.rrd";
+static data_source_t octets_dsrc[2] =
+{
+       {"queries",   DS_TYPE_COUNTER, 0, 125000000.0},
+       {"responses", DS_TYPE_COUNTER, 0, 125000000.0}
+};
 
-static char *traffic_ds_def[] =
+static data_set_t octets_ds =
 {
-       /* Limit to 1GBit/s */
-       "DS:queries:COUNTER:"COLLECTD_HEARTBEAT":0:125000000",
-       "DS:responses:COUNTER:"COLLECTD_HEARTBEAT":0:125000000",
-       NULL
+       "dns_octets", 2, octets_dsrc
 };
-static int traffic_ds_num = 2;
 
-static char *qtype_ds_def[] =
+static data_source_t counter_dsrc[1] =
 {
-       "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:65535",
-       NULL
+       {"value", DS_TYPE_COUNTER, 0, 65535.0}
 };
-static int qtype_ds_num = 1;
 
-static char *opcode_ds_def[] =
+static data_set_t qtype_ds =
 {
-       "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:65535",
-       NULL
+       "dns_qtype", 1, counter_dsrc
 };
-static int opcode_ds_num = 1;
 
-static char *rcode_ds_def[] =
+static data_set_t opcode_ds =
 {
-       "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:65535",
-       NULL
+       "dns_opcode", 1, counter_dsrc
+};
+
+static data_set_t rcode_ds =
+{
+       "dns_rcode", 1, counter_dsrc
 };
-static int rcode_ds_num = 1;
 
 #if DNS_HAVE_READ
-static char *config_keys[] =
+static const char *config_keys[] =
 {
        "Interface",
        "IgnoreSource",
@@ -101,8 +94,8 @@ static int config_keys_num = 2;
 #define PCAP_SNAPLEN 1460
 static char   *pcap_device = NULL;
 
-static unsigned int    tr_queries;
-static unsigned int    tr_responses;
+static counter_t       tr_queries;
+static counter_t       tr_responses;
 static counter_list_t *qtype_list;
 static counter_list_t *opcode_list;
 static counter_list_t *rcode_list;
@@ -191,7 +184,7 @@ static void counter_list_add (counter_list_t **list,
        DBG ("return ()");
 }
 
-static int dns_config (char *key, char *value)
+static int dns_config (const char *key, const char *value)
 {
        if (strcasecmp (key, "Interface") == 0)
        {
@@ -310,11 +303,9 @@ static void *dns_child_loop (void *dummy)
 
        return (NULL);
 } /* static void dns_child_loop (void) */
-#endif /* DNS_HAVE_READ */
 
-static void dns_init (void)
+static int dns_init (void)
 {
-#if DNS_HAVE_READ
        /* clean up an old thread */
        int status;
 
@@ -324,7 +315,7 @@ static void dns_init (void)
        pthread_mutex_unlock (&traffic_mutex);
 
        if (listen_thread_init != 0)
-               return;
+               return (-1);
 
        status = pthread_create (&listen_thread, NULL, dns_child_loop,
                        (void *) 0);
@@ -332,123 +323,50 @@ static void dns_init (void)
        {
                syslog (LOG_ERR, "dns plugin: pthread_create failed: %s",
                                strerror (status));
-               return;
+               return (-1);
        }
 
        listen_thread_init = 1;
-#endif /* DNS_HAVE_READ */
-}
-
-static void traffic_write (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, traffic_file, val,
-                       traffic_ds_def, traffic_ds_num);
-}
-
-static void qtype_write (char *host, char *inst, char *val)
-{
-       char file[512];
-       int status;
-
-       status = snprintf (file, 512, qtype_file, inst);
-       if (status < 1)
-               return;
-       else if (status >= 512)
-               return;
-
-       rrd_update_file (host, file, val, qtype_ds_def, qtype_ds_num);
-}
-
-static void rcode_write (char *host, char *inst, char *val)
-{
-       char file[512];
-       int status;
-
-       status = snprintf (file, 512, rcode_file, inst);
-       if (status < 1)
-               return;
-       else if (status >= 512)
-               return;
 
-       rrd_update_file (host, file, val, rcode_ds_def, rcode_ds_num);
-}
-
-static void opcode_write (char *host, char *inst, char *val)
-{
-       char file[512];
-       int status;
-
-       status = snprintf (file, 512, opcode_file, inst);
-       if (status < 1)
-               return;
-       else if (status >= 512)
-               return;
-
-       rrd_update_file (host, file, val, opcode_ds_def, opcode_ds_num);
-}
-
-#if DNS_HAVE_READ
-static void traffic_submit (unsigned int queries, unsigned int replies)
-{
-       char buffer[64];
-       int  status;
-
-       status = snprintf (buffer, 64, "N:%u:%u", queries, replies);
-       if ((status < 1) || (status >= 64))
-               return;
-
-       plugin_submit ("dns_traffic", "-", buffer);
-}
-
-static void qtype_submit (int qtype, unsigned int counter)
-{
-       char inst[32];
-       char buffer[32];
-       int  status;
-
-       strncpy (inst, qtype_str (qtype), 32);
-       inst[31] = '\0';
-
-       status = snprintf (buffer, 32, "N:%u", counter);
-       if ((status < 1) || (status >= 32))
-               return;
-
-       plugin_submit ("dns_qtype", inst, buffer);
-}
+       return (0);
+} /* int dns_init */
 
-static void rcode_submit (int rcode, unsigned int counter)
+static void submit_counter (const char *type, const char *type_instance,
+               counter_t value)
 {
-       char inst[32];
-       char buffer[32];
-       int  status;
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       strncpy (inst, rcode_str (rcode), 32);
-       inst[31] = '\0';
+       values[0].counter = value;
 
-       status = snprintf (buffer, 32, "N:%u", counter);
-       if ((status < 1) || (status >= 32))
-               return;
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "dns");
+       strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
-       plugin_submit ("dns_rcode", inst, buffer);
-}
+       plugin_dispatch_values (type, &vl);
+} /* void submit_counter */
 
-static void opcode_submit (int opcode, unsigned int counter)
+static void submit_octets (counter_t queries, counter_t responses)
 {
-       char inst[32];
-       char buffer[32];
-       int  status;
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       strncpy (inst, opcode_str (opcode), 32);
-       inst[31] = '\0';
+       values[0].counter = queries;
+       values[1].counter = responses;
 
-       status = snprintf (buffer, 32, "N:%u", counter);
-       if ((status < 1) || (status >= 32))
-               return;
+       vl.values = values;
+       vl.values_len = 2;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "dns");
 
-       plugin_submit ("dns_opcode", inst, buffer);
-}
+       plugin_dispatch_values ("dns_octets", &vl);
+} /* void submit_counter */
 
-static void dns_read (void)
+static int dns_read (void)
 {
        unsigned int keys[T_MAX];
        unsigned int values[T_MAX];
@@ -461,7 +379,7 @@ static void dns_read (void)
        values[0] = tr_queries;
        values[1] = tr_responses;
        pthread_mutex_unlock (&traffic_mutex);
-       traffic_submit (values[0], values[1]);
+       submit_octets (values[0], values[1]);
 
        pthread_mutex_lock (&qtype_mutex);
        for (ptr = qtype_list, len = 0;
@@ -476,7 +394,7 @@ static void dns_read (void)
        for (i = 0; i < len; i++)
        {
                DBG ("qtype = %u; counter = %u;", keys[i], values[i]);
-               qtype_submit (keys[i], values[i]);
+               submit_counter ("dns_qtype", qtype_str (keys[i]), values[i]);
        }
 
        pthread_mutex_lock (&opcode_mutex);
@@ -492,7 +410,7 @@ static void dns_read (void)
        for (i = 0; i < len; i++)
        {
                DBG ("opcode = %u; counter = %u;", keys[i], values[i]);
-               opcode_submit (keys[i], values[i]);
+               submit_counter ("dns_opcode", opcode_str (keys[i]), values[i]);
        }
 
        pthread_mutex_lock (&rcode_mutex);
@@ -508,23 +426,23 @@ static void dns_read (void)
        for (i = 0; i < len; i++)
        {
                DBG ("rcode = %u; counter = %u;", keys[i], values[i]);
-               rcode_submit (keys[i], values[i]);
+               submit_counter ("dns_rcode", rcode_str (keys[i]), values[i]);
        }
-}
-#else /* if !DNS_HAVE_READ */
-# define dns_read NULL
+
+       return (0);
+} /* int dns_read */
 #endif
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, dns_init, dns_read, NULL);
-       plugin_register ("dns_traffic", NULL, NULL, traffic_write);
-       plugin_register ("dns_qtype", NULL, NULL, qtype_write);
-       plugin_register ("dns_rcode", NULL, NULL, rcode_write);
-       plugin_register ("dns_opcode", NULL, NULL, opcode_write);
+       plugin_register_data_set (&octets_ds);
+       plugin_register_data_set (&qtype_ds);
+       plugin_register_data_set (&opcode_ds);
+       plugin_register_data_set (&rcode_ds);
+
 #if DNS_HAVE_READ
-       cf_register (MODULE_NAME, dns_config, config_keys, config_keys_num);
+       plugin_register_config ("dns", dns_config, config_keys, config_keys_num);
+       plugin_register_init ("dns", dns_init);
+       plugin_register_read ("dns", dns_read);
 #endif
-}
-
-#undef MODULE_NAME
+} /* void module_register */
index bbee9bb..ed0f9a2 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/email.c
- * Copyright (C) 2006  Sebastian Harl
+ * Copyright (C) 2006,2007  Sebastian Harl
  *
  * 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
@@ -42,9 +42,6 @@
 
 #if HAVE_LIBPTHREAD
 # include <pthread.h>
-# define EMAIL_HAVE_READ 1
-#else
-# define EMAIL_HAVE_READ 0
 #endif
 
 #if HAVE_SYS_SELECT_H
@@ -90,7 +87,6 @@
 /*
  * Private data structures
  */
-#if EMAIL_HAVE_READ
 /* linked list of email and check types */
 typedef struct type {
        char        *name;
@@ -128,21 +124,48 @@ typedef struct {
        conn_t *head;
        conn_t *tail;
 } conn_list_t;
-#endif /* EMAIL_HAVE_READ */
 
 /*
  * Private variables
  */
-#if EMAIL_HAVE_READ
 /* valid configuration file keys */
-static char *config_keys[] =
+static const char *config_keys[] =
 {
        "SocketGroup",
        "SocketPerms",
-       "MaxConns",
-       NULL
+       "MaxConns"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static data_source_t gauge_dsrc[1] =
+{
+       {"value", DS_TYPE_GAUGE, 0.0, NAN}
+};
+
+static data_set_t email_count_ds =
+{
+       "email_count", 1, gauge_dsrc
+};
+
+static data_set_t email_size_ds =
+{
+       "email_size", 1, gauge_dsrc
+};
+
+static data_set_t spam_check_ds =
+{
+       "spam_check", 1, gauge_dsrc
+};
+
+static data_source_t spam_score_dsrc[1] =
+{
+       {"score", DS_TYPE_GAUGE, NAN, NAN}
+};
+
+static data_set_t spam_score_ds =
+{
+       "spam_score", 1, spam_score_dsrc
 };
-static int config_keys_num = 3;
 
 /* socket configuration */
 static char *sock_group = COLLECTD_GRP_NAME;
@@ -184,42 +207,11 @@ static int score_count;
 
 static pthread_mutex_t check_mutex = PTHREAD_MUTEX_INITIALIZER;
 static type_list_t check;
-#endif /* EMAIL_HAVE_READ */
 
-#define COUNT_FILE "email/email-%s.rrd"
-static char *count_ds_def[] =
-{
-       "DS:count:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       NULL
-};
-static int count_ds_num = 1;
-
-#define SIZE_FILE  "email/email_size-%s.rrd"
-static char *size_ds_def[] =
-{
-       "DS:size:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       NULL
-};
-static int size_ds_num = 1;
-
-#define SCORE_FILE "email/spam_score.rrd"
-static char *score_ds_def[] =
-{
-       "DS:score:GAUGE:"COLLECTD_HEARTBEAT":U:U",
-       NULL
-};
-static int score_ds_num = 1;
-
-#define CHECK_FILE "email/spam_check-%s.rrd"
-static char *check_ds_def[] =
-{
-       "DS:hits:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       NULL
-};
-static int check_ds_num = 1;
-
-#if EMAIL_HAVE_READ
-static int email_config (char *key, char *value)
+/*
+ * Private functions
+ */
+static int email_config (const char *key, const char *value)
 {
        if (0 == strcasecmp (key, "SocketGroup")) {
                sock_group = sstrdup (value);
@@ -563,21 +555,33 @@ static void *open_connection (void *arg)
                pthread_exit ((void *)1);
        }
 
-       if ((uid_t)0 == geteuid ()) {
+       if ((uid_t) 0 == geteuid ())
+       {
+               struct group sg;
                struct group *grp;
-
-               errno = 0;
-               if (NULL != (grp = getgrnam (sock_group))) {
-                       errno = 0;
-                       if (0 != chown (SOCK_PATH, (uid_t)-1, grp->gr_gid)) {
-                               log_warn ("chown() failed: %s", strerror (errno));
-                       }
+               char grbuf[2048];
+               int status;
+
+               grp = NULL;
+               status = getgrnam_r (sock_group, &sg, grbuf, sizeof (grbuf), &grp);
+               if (status != 0)
+               {
+                       log_warn ("getgrnam_r (%s) failed: %s", sock_group, strerror (status));
                }
-               else {
-                       log_warn ("getgrnam() failed: %s", strerror (errno));
+               else if (grp == NULL)
+               {
+                       log_warn ("No such group: `%s'", sock_group);
+               }
+               else
+               {
+                       status = chown (SOCK_PATH, (uid_t) -1, grp->gr_gid);
+                       if (status != 0)
+                               log_warn ("chown (%s, -1, %i) failed: %s",
+                                               SOCK_PATH, (int) grp->gr_gid, strerror (errno));
                }
        }
-       else {
+       else /* geteuid != 0 */
+       {
                log_warn ("not running as root");
        }
 
@@ -664,30 +668,27 @@ static void *open_connection (void *arg)
        }
        pthread_exit ((void *)0);
 } /* static void *open_connection (void *) */
-#endif /* EMAIL_HAVE_READ */
 
-static void email_init (void)
+static int email_init (void)
 {
-#if EMAIL_HAVE_READ
        int err = 0;
 
        if (0 != (err = pthread_create (&connector, NULL,
                                open_connection, NULL))) {
                disabled = 1;
                log_err ("pthread_create() failed: %s", strerror (err));
-               return;
+               return (-1);
        }
-#endif /* EMAIL_HAVE_READ */
-       return;
-} /* static void email_init (void) */
 
-#if EMAIL_HAVE_READ
-static void email_shutdown (void)
+       return (0);
+} /* int email_init */
+
+static int email_shutdown (void)
 {
        int i = 0;
 
        if (disabled)
-               return;
+               return (0);
 
        pthread_kill (connector, SIGTERM);
        close (connector_socket);
@@ -703,81 +704,26 @@ static void email_shutdown (void)
        pthread_mutex_unlock (&conns_mutex);
 
        unlink (SOCK_PATH);
-       return;
-} /* static void email_shutdown (void) */
-#endif /* EMAIL_HAVE_READ */
-
-static void count_write (char *host, char *inst, char *val)
-{
-       char file[BUFSIZE] = "";
-       int  len           = 0;
 
-       len = snprintf (file, BUFSIZE, COUNT_FILE, inst);
-       if ((len < 0) || (len >= BUFSIZE))
-               return;
-
-       rrd_update_file (host, file, val, count_ds_def, count_ds_num);
-       return;
-} /* static void email_write (char *host, char *inst, char *val) */
-
-static void size_write (char *host, char *inst, char *val)
-{
-       char file[BUFSIZE] = "";
-       int  len           = 0;
-
-       len = snprintf (file, BUFSIZE, SIZE_FILE, inst);
-       if ((len < 0) || (len >= BUFSIZE))
-               return;
-
-       rrd_update_file (host, file, val, size_ds_def, size_ds_num);
-       return;
-} /* static void size_write (char *host, char *inst, char *val) */
-
-static void score_write (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, SCORE_FILE, val, score_ds_def, score_ds_num);
-       return;
-} /* static void score_write (char *host, char *inst, char *val) */
-
-static void check_write (char *host, char *inst, char *val)
-{
-       char file[BUFSIZE] = "";
-       int  len           = 0;
-
-       len = snprintf (file, BUFSIZE, CHECK_FILE, inst);
-       if ((len < 0) || (len >= BUFSIZE))
-               return;
-
-       rrd_update_file (host, file, val, check_ds_def, check_ds_num);
-       return;
-} /* static void check_write (char *host, char *inst, char *val) */
+       return (0);
+} /* static void email_shutdown (void) */
 
-#if EMAIL_HAVE_READ
-static void type_submit (char *plugin, char *inst, int value)
+static void email_submit (const char *type, const char *type_instance, gauge_t value)
 {
-       char buf[BUFSIZE] = "";
-       int  len          = 0;
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       len = snprintf (buf, BUFSIZE, "%u:%i", (unsigned int)curtime, value);
-       if ((len < 0) || (len >= BUFSIZE))
-               return;
+       values[0].gauge = value;
 
-       plugin_submit (plugin, inst, buf);
-       return;
-} /* static void type_submit (char *, char *, int) */
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "email");
+       strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
-static void score_submit (double value)
-{
-       char buf[BUFSIZE] = "";
-       int  len          = 0;
-
-       len = snprintf (buf, BUFSIZE, "%u:%.2f", (unsigned int)curtime, value);
-       if ((len < 0) || (len >= BUFSIZE))
-               return;
-
-       plugin_submit ("email_spam_score", "-", buf);
-       return;
-} /* static void score_submit (double) */
+       plugin_dispatch_values (type, &vl);
+} /* void email_submit */
 
 /* Copy list l1 to list l2. l2 may partly exist already, but it is assumed
  * that neither the order nor the name of any element of either list is
@@ -817,7 +763,7 @@ static void copy_type_list (type_list_t *l1, type_list_t *l2)
        return;
 }
 
-static void email_read (void)
+static int email_read (void)
 {
        type_t *ptr;
 
@@ -828,7 +774,7 @@ static void email_read (void)
        static type_list_t *chk;
 
        if (disabled)
-               return;
+               return (-1);
 
        if (NULL == cnt) {
                cnt = (type_list_t *)smalloc (sizeof (type_list_t));
@@ -853,7 +799,7 @@ static void email_read (void)
        pthread_mutex_unlock (&count_mutex);
 
        for (ptr = cnt->head; NULL != ptr; ptr = ptr->next) {
-               type_submit ("email_count", ptr->name, ptr->value);
+               email_submit ("email_count", ptr->name, ptr->value);
        }
 
        /* email size */
@@ -864,7 +810,7 @@ static void email_read (void)
        pthread_mutex_unlock (&size_mutex);
 
        for (ptr = sz->head; NULL != ptr; ptr = ptr->next) {
-               type_submit ("email_size", ptr->name, ptr->value);
+               email_submit ("email_size", ptr->name, ptr->value);
        }
 
        /* spam score */
@@ -876,7 +822,7 @@ static void email_read (void)
 
        pthread_mutex_unlock (&score_mutex);
 
-       score_submit (sc);
+       email_submit ("spam_score", "", sc);
 
        /* spam checks */
        pthread_mutex_lock (&check_mutex);
@@ -885,27 +831,23 @@ static void email_read (void)
 
        pthread_mutex_unlock (&check_mutex);
 
-       for (ptr = chk->head; NULL != ptr; ptr = ptr->next) {
-               type_submit ("email_spam_check", ptr->name, ptr->value);
-       }
-       return;
-} /* static void read (void) */
-#else /* if !EMAIL_HAVE_READ */
-# define email_read NULL
-#endif
+       for (ptr = chk->head; NULL != ptr; ptr = ptr->next)
+               email_submit ("spam_check", ptr->name, ptr->value);
+
+       return (0);
+} /* int email_read */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, email_init, email_read, NULL);
-       plugin_register ("email_count", NULL, NULL, count_write);
-       plugin_register ("email_size", NULL, NULL, size_write);
-       plugin_register ("email_spam_score", NULL, NULL, score_write);
-       plugin_register ("email_spam_check", NULL, NULL, check_write);
-#if EMAIL_HAVE_READ
-       plugin_register_shutdown (MODULE_NAME, email_shutdown);
-       cf_register (MODULE_NAME, email_config, config_keys, config_keys_num);
-#endif /* EMAIL_HAVE_READ */
-       return;
+       plugin_register_data_set (&email_count_ds);
+       plugin_register_data_set (&email_size_ds);
+       plugin_register_data_set (&spam_check_ds);
+       plugin_register_data_set (&spam_score_ds);
+
+       plugin_register_config ("email", email_config, config_keys, config_keys_num);
+       plugin_register_init ("email", email_init);
+       plugin_register_read ("email", email_read);
+       plugin_register_shutdown ("email", email_shutdown);
 } /* void module_register (void) */
 
 /* vim: set sw=4 ts=4 tw=78 noexpandtab : */
diff --git a/src/entropy.c b/src/entropy.c
new file mode 100644 (file)
index 0000000..68c57da
--- /dev/null
@@ -0,0 +1,97 @@
+/**
+ * collectd - src/entropy.c
+ * Copyright (C) 2005,2006  Florian octo Forster
+ *
+ * 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; only version 2 of the License is applicable.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if KERNEL_LINUX
+# define ENTROPY_HAVE_READ 1
+#else
+# define ENTROPY_HAVE_READ 0
+#endif
+
+#define ENTROPY_FILE "/proc/sys/kernel/random/entropy_avail"
+
+static data_source_t dsrc[1] =
+{
+       {"entropy",  DS_TYPE_GAUGE, 0.0, 4294967295.0}
+};
+
+static data_set_t ds =
+{
+       "entropy", 1, dsrc
+};
+
+#if ENTROPY_HAVE_READ
+static void entropy_submit (double entropy)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = entropy;
+
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "entropy");
+       strcpy (vl.plugin_instance, "");
+       strcpy (vl.type_instance, "");
+
+       plugin_dispatch_values ("entropy", &vl);
+}
+
+static int entropy_read (void)
+{
+#if KERNEL_LINUX
+       double entropy;
+       FILE *fh;
+       char buffer[64];
+
+       fh = fopen (ENTROPY_FILE, "r");
+       if (fh == NULL)
+               return (-1);
+
+       if (fgets (buffer, sizeof (buffer), fh) == NULL)
+       {
+               fclose (fh);
+               return (-1);
+       }
+       fclose (fh);
+
+       entropy = atof (buffer);
+       
+       if (entropy > 0.0)
+               entropy_submit (entropy);
+#endif /* KERNEL_LINUX */
+
+       return (0);
+}
+#endif /* ENTROPY_HAVE_READ */
+
+void module_register (void)
+{
+       plugin_register_data_set (&ds);
+#if ENTROPY_HAVE_READ
+       plugin_register_read ("entropy", entropy_read);
+#endif
+}
diff --git a/src/exec.c b/src/exec.c
new file mode 100644 (file)
index 0000000..63401be
--- /dev/null
@@ -0,0 +1,361 @@
+/**
+ * collectd - src/exec.c
+ * Copyright (C) 2007  Florian octo Forster
+ *
+ * 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; only version 2 of the License is applicable.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_debug.h"
+
+#include <sys/types.h>
+#include <pwd.h>
+
+#include <pthread.h>
+
+/*
+ * Private data types
+ */
+struct program_list_s;
+typedef struct program_list_s program_list_t;
+struct program_list_s
+{
+  char           *user;
+  char           *exec;
+  int             pid;
+  program_list_t *next;
+};
+
+/*
+ * Private variables
+ */
+static data_source_t dsrc_counter[1] =
+{
+  {"value", DS_TYPE_COUNTER, NAN, NAN}
+};
+
+static data_set_t ds_counter =
+{
+  "counter", STATIC_ARRAY_SIZE (dsrc_counter), dsrc_counter
+};
+
+static data_source_t dsrc_gauge[1] =
+{
+  {"value", DS_TYPE_GAUGE, NAN, NAN}
+};
+
+static data_set_t ds_gauge =
+{
+  "gauge", STATIC_ARRAY_SIZE (dsrc_gauge), dsrc_gauge
+};
+
+static const char *config_keys[] =
+{
+  "Exec"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static program_list_t *pl_head = NULL;
+
+/*
+ * Functions
+ */
+static int exec_config (const char *key, const char *value)
+{
+  if (strcasecmp ("Exec", key) == 0)
+  {
+    program_list_t *pl;
+    pl = (program_list_t *) malloc (sizeof (program_list_t));
+    if (pl == NULL)
+      return (1);
+    memset (pl, '\0', sizeof (program_list_t));
+
+    pl->user = strdup (value);
+    if (pl->user == NULL)
+    {
+      sfree (pl);
+      return (1);
+    }
+
+    pl->exec = strchr (pl->user, ' ');
+    if (pl->exec == NULL)
+    {
+      sfree (pl->user);
+      sfree (pl);
+      return (1);
+    }
+    while (*pl->exec == ' ')
+    {
+      *pl->exec = '\0';
+      pl->exec++;
+    }
+
+    if (*pl->exec == '\0')
+    {
+      sfree (pl->user);
+      sfree (pl);
+      return (1);
+    }
+
+    pl->next = pl_head;
+    pl_head = pl;
+  }
+  else
+  {
+    return (-1);
+  }
+
+  return (0);
+} /* int exec_config */
+
+static void submit_counter (const char *type_instance, counter_t value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  DBG ("type_instance = %s; value = %llu;", type_instance, value);
+
+  values[0].counter = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  vl.time = time (NULL);
+  strcpy (vl.host, hostname_g);
+  strcpy (vl.plugin, "exec");
+  strcpy (vl.plugin_instance, "");
+  strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values ("counter", &vl);
+} /* void submit_counter */
+
+static void submit_gauge (const char *type_instance, gauge_t value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  DBG ("type_instance = %s; value = %lf;", type_instance, value);
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  vl.time = time (NULL);
+  strcpy (vl.host, hostname_g);
+  strcpy (vl.plugin, "exec");
+  strcpy (vl.plugin_instance, "");
+  strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values ("gauge", &vl);
+} /* void submit_counter */
+
+static void exec_child (program_list_t *pl)
+{
+  int status;
+  int uid;
+  char *arg0;
+
+  struct passwd *sp_ptr;
+  struct passwd sp;
+  char pwnambuf[2048];
+
+  sp_ptr = NULL;
+  status = getpwnam_r (pl->user, &sp, pwnambuf, sizeof (pwnambuf), &sp_ptr);
+  if (status != 0)
+  {
+    syslog (LOG_ERR, "exec plugin: getpwnam_r failed: %s", strerror (status));
+    exit (-1);
+  }
+  if (sp_ptr == NULL)
+  {
+    syslog (LOG_ERR, "exec plugin: No such user: `%s'", pl->user);
+    exit (-1);
+  }
+
+  uid = sp.pw_uid;
+  if (uid == 0)
+  {
+    syslog (LOG_ERR, "exec plugin: Cowardly refusing to exec program as root.");
+    exit (-1);
+  }
+
+  status = setuid (uid);
+  if (status != 0)
+  {
+    syslog (LOG_ERR, "exec plugin: setuid failed: %s", strerror (errno));
+    exit (-1);
+  }
+
+  arg0 = strrchr (pl->exec, '/');
+  if (arg0 != NULL)
+    arg0++;
+  if ((arg0 == NULL) || (*arg0 == '\0'))
+    arg0 = pl->exec;
+
+  status = execlp (pl->exec, arg0, (char *) 0);
+
+  syslog (LOG_ERR, "exec plugin: exec failed: %s", strerror (errno));
+  exit (-1);
+} /* void exec_child */
+
+static int fork_child (program_list_t *pl)
+{
+  int fd_pipe[2];
+  int status;
+
+  if (pl->pid != 0)
+    return (-1);
+
+  status = pipe (fd_pipe);
+  if (status != 0)
+  {
+    syslog (LOG_ERR, "exec plugin: pipe failed: %s", strerror (errno));
+    return (-1);
+  }
+
+  pl->pid = fork ();
+  if (pl->pid < 0)
+  {
+    syslog (LOG_ERR, "exec plugin: fork failed: %s", strerror (errno));
+    return (-1);
+  }
+  else if (pl->pid == 0)
+  {
+    close (fd_pipe[0]);
+
+    /* Connect the pipe to STDOUT and STDERR */
+    if (fd_pipe[1] != STDOUT_FILENO)
+      dup2 (fd_pipe[1], STDOUT_FILENO);
+    if (fd_pipe[1] != STDERR_FILENO)
+      dup2 (fd_pipe[1], STDERR_FILENO);
+    if ((fd_pipe[1] != STDOUT_FILENO) && (fd_pipe[1] != STDERR_FILENO))
+      close (fd_pipe[1]);
+
+    exec_child (pl);
+    /* does not return */
+  }
+
+  close (fd_pipe[1]);
+  return (fd_pipe[0]);
+} /* int fork_child */
+
+static void *exec_read_one (void *arg)
+{
+  program_list_t *pl = (program_list_t *) arg;
+  int fd;
+  FILE *fh;
+  char buffer[1024];
+
+  fd = fork_child (pl);
+  if (fd < 0)
+    pthread_exit ((void *) 1);
+
+  assert (pl->pid != 0);
+
+  fh = fdopen (fd, "r");
+  if (fh == NULL)
+  {
+    syslog (LOG_ERR, "exec plugin: fdopen (%i) failed: %s", fd,
+       strerror (errno));
+    kill (pl->pid, SIGTERM);
+    close (fd);
+    pthread_exit ((void *) 1);
+  }
+
+  while (fgets (buffer, sizeof (buffer), fh) != NULL)
+  {
+    int len;
+    char *type;
+    char *type_instance;
+    char *value;
+
+    DBG ("buffer = %s", buffer);
+
+    len = strlen (buffer);
+    if (len < 5)
+      continue;
+
+    if (buffer[0] == '#')
+      continue;
+
+    type = buffer;
+
+    type_instance = strchr (type, ',');
+    if (type_instance == NULL)
+      continue;
+    *type_instance = '\0';
+    type_instance++;
+
+    if ((strcasecmp ("counter", type) != 0)
+       && (strcasecmp ("gauge", type) != 0))
+    {
+      syslog (LOG_WARNING, "exec plugin: Received invalid type: %s", type);
+      continue;
+    }
+
+    value = strchr (type_instance, ',');
+    if (value == NULL)
+      continue;
+    *value = '\0';
+    value++;
+
+    DBG ("value = %s", value);
+
+    if (strcasecmp ("counter", type) == 0)
+      submit_counter (type_instance, atoll (value));
+    else
+      submit_gauge (type_instance, atof (value));
+  } /* while (fgets) */
+
+  fclose (fh);
+  pl->pid = 0;
+
+  pthread_exit ((void *) 0);
+} /* void *exec_read_one */
+
+static int exec_read (void)
+{
+  program_list_t *pl;
+
+  for (pl = pl_head; pl != NULL; pl = pl->next)
+  {
+    pthread_t t;
+    pthread_attr_t attr;
+
+    if (pl->pid != 0)
+      continue;
+
+    pthread_attr_init (&attr);
+    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+    pthread_create (&t, &attr, exec_read_one, (void *) pl);
+  } /* for (pl) */
+
+  return (0);
+} /* int exec_read */
+
+void module_register (void)
+{
+  plugin_register_data_set (&ds_counter);
+  plugin_register_data_set (&ds_gauge);
+  plugin_register_config ("exec", exec_config, config_keys, config_keys_num);
+  plugin_register_read ("exec", exec_read);
+} /* void module_register */
+
+/*
+ * vim:shiftwidth=2:softtabstop=2:tabstop=8
+ */
index 80b3419..353fbe3 100644 (file)
 #include "configfile.h"
 #include "utils_debug.h"
 
-#define MODULE_NAME "hddtemp"
-
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <libgen.h> /* for basename */
+#if HAVE_NETDB_H && HAVE_SYS_SOCKET_H && HAVE_NETINET_IN_H \
+       && HAVE_NETINET_TCP_H && HAVE_LIBGEN_H
+# include <netdb.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# include <libgen.h> /* for basename */
+# define HDDTEMP_HAVE_READ 1
+#else
+# define HDDTEMP_HAVE_READ 0
+#endif
 
 #if HAVE_LINUX_MAJOR_H
 # include <linux/major.h>
 #define HDDTEMP_DEF_HOST "127.0.0.1"
 #define HDDTEMP_DEF_PORT "7634"
 
-/* BUFFER_SIZE
-   Size of the buffer we use to receive from the hddtemp daemon. */
-#define BUFFER_SIZE 1024
-
-static char *filename_format = "hddtemp-%s.rrd";
+static data_source_t data_source_temperature[1] =
+{
+       {"value", DS_TYPE_GAUGE, -273.15, NAN}
+};
 
-static char *ds_def[] =
+static data_set_t temperature_ds =
 {
-       "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
-       NULL
+       "temperature", 1, data_source_temperature
 };
-static int ds_num = 1;
 
-static char *config_keys[] =
+#if HDDTEMP_HAVE_READ
+static const char *config_keys[] =
 {
        "Host",
        "Port",
@@ -211,7 +213,7 @@ static int hddtemp_query_daemon (char *buffer, int buffer_size)
        return (0);
 }
 
-static int hddtemp_config (char *key, char *value)
+static int hddtemp_config (const char *key, const char *value)
 {
        if (strcasecmp (key, "host") == 0)
        {
@@ -236,11 +238,11 @@ static int hddtemp_config (char *key, char *value)
 /* In the init-function we initialize the `hddname_t' list used to translate
  * disk-names. Under Linux that's done using `/proc/partitions'. Under other
  * operating-systems, it's not done at all. */
-static void hddtemp_init (void)
+static int hddtemp_init (void)
 {
 #if KERNEL_LINUX
        FILE *fh;
-       char buf[BUFFER_SIZE];
+       char buf[1024];
        int buflen;
 
        char *fields[16];
@@ -267,7 +269,7 @@ static void hddtemp_init (void)
        {
                DBG ("Looking at /proc/partitions...");
 
-               while (fgets (buf, BUFFER_SIZE, fh) != NULL)
+               while (fgets (buf, sizeof (buf), fh) != NULL)
                {
                        /* Delete trailing newlines */
                        buflen = strlen (buf);
@@ -380,22 +382,9 @@ static void hddtemp_init (void)
                DBG ("Could not open /proc/partitions: %s",
                                strerror (errno));
 #endif /* KERNEL_LINUX */
-}
 
-static void hddtemp_write (char *host, char *inst, char *val)
-{
-       char filename[BUFFER_SIZE];
-       int status;
-
-       /* construct filename */
-       status = snprintf (filename, BUFFER_SIZE, filename_format, inst);
-       if (status < 1)
-               return;
-       else if (status >= BUFFER_SIZE)
-               return;
-
-       rrd_update_file (host, filename, val, ds_def, ds_num);
-}
+       return (0);
+} /* int hddtemp_init */
 
 /*
  * hddtemp_get_name
@@ -432,60 +421,42 @@ static char *hddtemp_get_name (char *drive)
        return (ret);
 }
 
-static void hddtemp_submit (char *inst, double temperature)
+static void hddtemp_submit (char *type_instance, double value)
 {
-       char buf[BUFFER_SIZE];
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
 
-       if (snprintf (buf, BUFFER_SIZE, "%u:%.3f", (unsigned int) curtime, temperature)
-            >= BUFFER_SIZE)
-               return;
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "hddtemp");
+       strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
-       plugin_submit (MODULE_NAME, inst, buf);
+       plugin_dispatch_values ("temperature", &vl);
 }
 
-static void hddtemp_read (void)
+static int hddtemp_read (void)
 {
-       char buf[BUFFER_SIZE];
+       char buf[1024];
        char *fields[128];
        char *ptr;
+       char *saveptr;
        int num_fields;
        int num_disks;
        int i;
 
-       static int wait_time = 1;
-       static int wait_left = 0;
-
-       if (wait_left >= 10)
-       {
-               wait_left -= 10;
-               return;
-       }
-
        /* get data from daemon */
-       if (hddtemp_query_daemon (buf, BUFFER_SIZE) < 0)
-       {
-               /* This limit is reached in log2(86400) =~ 17 steps. Since
-                * there is a 2^n seconds wait between each step it will need
-                * roughly one day to reach this limit. -octo */
-               
-               wait_time *= 2;
-               if (wait_time > 86400)
-                       wait_time = 86400;
-
-               wait_left = wait_time;
-
-               return;
-       }
-       else
-       {
-               wait_time = 1;
-               wait_left = 0;
-       }
+       if (hddtemp_query_daemon (buf, sizeof (buf)) < 0)
+               return (-1);
 
-       /* NB: strtok will eat up "||" and leading "|"'s */
+       /* NB: strtok_r will eat up "||" and leading "|"'s */
        num_fields = 0;
        ptr = buf;
-       while ((fields[num_fields] = strtok (ptr, "|")) != NULL)
+       saveptr = NULL;
+       while ((fields[num_fields] = strtok_r (ptr, "|", &saveptr)) != NULL)
        {
                ptr = NULL;
                num_fields++;
@@ -525,14 +496,21 @@ static void hddtemp_read (void)
                        hddtemp_submit (name, temperature);
                }
        }
-}
+       
+       return (0);
+} /* int hddtemp_read */
+#endif /* HDDTEMP_HAVE_READ */
 
 /* module_register
    Register collectd plugin. */
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, hddtemp_init, hddtemp_read, hddtemp_write);
-       cf_register (MODULE_NAME, hddtemp_config, config_keys, config_keys_num);
+       plugin_register_data_set (&temperature_ds);
+       
+#if HDDTEMP_HAVE_READ
+       plugin_register_config ("hddtemp", hddtemp_config,
+                       config_keys, config_keys_num);
+       plugin_register_init ("hddtemp", hddtemp_init);
+       plugin_register_read ("hddtemp", hddtemp_read);
+#endif /* HDDTEMP_HAVE_READ */
 }
-
-#undef MODULE_NAME
index 69a3196..6c30e95 100644 (file)
--- a/src/irq.c
+++ b/src/irq.c
 /*
  * (Module-)Global variables
  */
-static char *irq_file   = "irq/irq-%s.rrd";
+static data_source_t dsrc_irq[1] =
+{
+       {"value", DS_TYPE_COUNTER, 0, 65535.0}
+};
 
-static char *config_keys[] =
+static data_set_t ds_irq =
 {
-       "Irq",
-       "IgnoreSelected",
-       NULL
+       "irq", 1, dsrc_irq
 };
-static int config_keys_num = 2;
 
-static char *ds_def[] =
+#if IRQ_HAVE_READ
+static const char *config_keys[] =
 {
-       "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:65535",
-       NULL
+       "Irq",
+       "IgnoreSelected"
 };
-static int ds_num = 1;
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
 static unsigned int *irq_list;
 static unsigned int irq_list_num;
@@ -65,7 +66,7 @@ static unsigned int irq_list_num;
  */
 static int irq_list_action;
 
-static int irq_config (char *key, char *value)
+static int irq_config (const char *key, const char *value)
 {
        if (strcasecmp (key, "Irq") == 0)
        {
@@ -132,46 +133,32 @@ static int check_ignore_irq (const unsigned int irq)
        return (1 - irq_list_action);
 }
 
-static void irq_write (char *host, char *inst, char *value)
+static void irq_submit (unsigned int irq, counter_t value)
 {
-       char file[BUFSIZE];
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
        int status;
 
-       if (check_ignore_irq (atoi(inst)))
-               return;
-
-       status = snprintf (file, BUFSIZE, irq_file, inst);
-       if (status < 1)
-               return;
-       else if (status >= BUFSIZE)
-               return;
-
-       rrd_update_file (host, file, value, ds_def, ds_num);
-}
-
-#if IRQ_HAVE_READ
-static void irq_submit (unsigned int irq, unsigned int value)
-{
-       char value_str[32];
-       char type_str[16];
-       int  status;
-
        if (check_ignore_irq (irq))
                return;
 
-       status = snprintf (value_str, 32, "%u:%u",
-                               (unsigned int) curtime, value);
-       if ((status >= 32) || (status < 1))
-               return;
+       values[0].counter = value;
 
-       status = snprintf (type_str, 16, "%u", irq);
-       if ((status >= 16) || (status < 1))
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "irq");
+
+       status = snprintf (vl.type_instance, sizeof (vl.type_instance),
+                       "%u", irq);
+       if ((status < 1) || (status >= sizeof (vl.type_instance)))
                return;
 
-       plugin_submit (MODULE_NAME, type_str, value_str);
+       plugin_dispatch_values ("irq", &vl);
 } /* void irq_submit */
 
-static void irq_read (void)
+static int irq_read (void)
 {
 #if KERNEL_LINUX
 
@@ -193,7 +180,7 @@ static void irq_read (void)
        {
                syslog (LOG_WARNING, "irq plugin: fopen (/proc/interrupts): %s",
                                strerror (errno));
-               return;
+               return (-1);
        }
        while (fgets (buffer, BUFSIZE, fh) != NULL)
        {
@@ -223,15 +210,20 @@ static void irq_read (void)
        }
        fclose (fh);
 #endif /* KERNEL_LINUX */
-} /* void irq_read */
-#else
-#define irq_read NULL
+
+       return (0);
+} /* int irq_read */
 #endif /* IRQ_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, NULL, irq_read, irq_write);
-       cf_register (MODULE_NAME, irq_config, config_keys, config_keys_num);
+       plugin_register_data_set (&ds_irq);
+
+#if IRQ_HAVE_READ
+       plugin_register_config ("irq", irq_config,
+                       config_keys, config_keys_num);
+       plugin_register_read ("irq", irq_read);
+#endif /* IRQ_HAVE_READ */
 }
 
 #undef BUFSIZE
diff --git a/src/libconfig/AUTHORS b/src/libconfig/AUTHORS
deleted file mode 100644 (file)
index 53f27bf..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-                                libconfig 0.1.21
-
-Release information:
-  pkg:  libconfig version 0.1.21
-  url:  http://www.rkeene.org/files/oss/libconfig/devel/libconfig-0.1.21.tar.gz
-  web:  http://www.rkeene.org/oss/libconfig/
-  date: Tue Oct 18 16:03:55 CDT 2005
-  mail: libconfig@rkeene.org
---------------------------------------------------------------------------
-
-Primary Authors:
-  * Roy Keene <libconfig@rkeene.org>
-    Primary maintainer.
-
-People who have submitted patches:
-  * Mirko Buffoni <mirko.buffoni@synthesys.it>
-    Fixed installation issues and corrected mistakes in RPM spec file.
diff --git a/src/libconfig/LICENSE b/src/libconfig/LICENSE
deleted file mode 100644 (file)
index 4af06fb..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2004  Roy Keene, Keene Enterprises
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/src/libconfig/Makefile.am b/src/libconfig/Makefile.am
deleted file mode 100644 (file)
index b5a558a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-AUTOMAKE_OPTIONS = foreign no-dependencies
-
-EXTRA_DIST = AUTHORS LICENSE README TODO
-
-noinst_LTLIBRARIES = libconfig.la
-
-libconfig_la_CFLAGS =
-libconfig_la_LDFLAGS = -avoid-version
-libconfig_la_SOURCES = \
-       libconfig.c libconfig.h \
-       conf_apache.c conf_apache.h \
-       conf_colon.c conf_colon.h \
-       conf_equal.c conf_equal.h \
-       conf_section.c conf_section.h \
-       conf_space.c conf_space.h \
-       conf_xml.c conf_xml.h \
-       compat.h libconfig_private.h
diff --git a/src/libconfig/README b/src/libconfig/README
deleted file mode 100644 (file)
index 7274223..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-                                libconfig 0.1.21
-
-Release information:
-  pkg:  libconfig version 0.1.21
-  url:  http://www.rkeene.org/files/oss/libconfig/devel/libconfig-0.1.21.tar.gz
-  web:  http://www.rkeene.org/oss/libconfig/
-  date: Tue Oct 18 16:03:55 CDT 2005
-  mail: libconfig@rkeene.org
---------------------------------------------------------------------------
-
-Tested platforms:
-  Mac OS X 10.1
-  HP-UX 11.11
-  NetBSD 1.6.1
-  FreeBSD 4.8
-  OpenBSD 3.4
-  SunOS 5.9
-  Linux (Slackware, RedHat, Fedora Core, Debian)
-  IRIX 6.5
diff --git a/src/libconfig/TODO b/src/libconfig/TODO
deleted file mode 100644 (file)
index 6ba4ed3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-                                libconfig 0.1.21
-
-Release information:
-  pkg:  libconfig version 0.1.21
-  url:  http://www.rkeene.org/files/oss/libconfig/devel/libconfig-0.1.21.tar.gz
-  web:  http://www.rkeene.org/oss/libconfig/
-  date: Tue Oct 18 16:03:55 CDT 2005
-  mail: libconfig@rkeene.org
---------------------------------------------------------------------------
-
-  More manual pages.
diff --git a/src/libconfig/compat.h b/src/libconfig/compat.h
deleted file mode 100644 (file)
index 48d0b07..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef RSK_COMPAT_H
-#define RSK_COMPAT_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#ifdef __WIN32__
-#include "win32.h"
-#endif
-
-#ifndef LC_LINEBUF_LEN
-#define LC_LINEBUF_LEN 1024
-#endif
-
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
-#ifdef HAVE_OPENNET_H
-#include <opennet.h>
-#endif
-#ifdef HAVE_LIBOPENNET
-#define lc_fopen(path, mode) fopen_net(path, mode)
-#define lc_fgets(buf, size, stream) fgets_net(buf, size, stream)
-#define lc_feof(stream) feof_net(stream)
-#define lc_fclose(stream) fclose_net(stream)
-#define LC_FILE NETFILE
-#else
-#define lc_fopen(path, mode) fopen(path, mode)
-#define lc_fgets(buf, size, stream) fgets(buf, size, stream)
-#define lc_feof(stream) feof(stream)
-#define lc_fclose(stream) fclose(stream)
-#define LC_FILE FILE
-#endif
-
-#endif
diff --git a/src/libconfig/conf_apache.c b/src/libconfig/conf_apache.c
deleted file mode 100644 (file)
index 1497d1e..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-#include "compat.h"
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_apache.h"
-
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-
-static int lc_process_conf_apache_file(const char *configfile, const char *pathprefix);
-
-static int lc_process_conf_apache_include(const char *pathname, const char *pathprefix) {
-       struct stat pathinfo;
-       struct dirent *dinfo = NULL;
-       char includepath[LC_LINEBUF_LEN] = {0};
-       DIR *dh = NULL;
-       int statret = -1, lcpcafret = -1;
-       int retval = 0;
-
-       statret = stat(pathname, &pathinfo);
-       if (statret < 0) {
-               return(-1);
-       }
-
-       if (S_ISDIR(pathinfo.st_mode)) {
-               dh = opendir(pathname);
-               if (dh == NULL) {
-                       return(-1);
-               }
-
-               while (1) {
-                       dinfo = readdir(dh);
-                       if (dinfo == NULL) {
-                               break;
-                       }
-
-                       /* Skip files that begin with a dot ('.') */
-                       if (dinfo->d_name[0] == '.') continue;
-
-                       snprintf(includepath, sizeof(includepath) - 1, "%s/%s", pathname, dinfo->d_name);
-                       lcpcafret = lc_process_conf_apache_include(includepath, pathprefix);
-                       if (lcpcafret < 0) {
-                               retval = -1;
-                               /* XXX: should we break here (abort further including of files from a directory if one fails ?) */
-                       }
-               }
-
-               closedir(dh);
-       } else {
-               lcpcafret = lc_process_conf_apache_file(pathname, pathprefix);
-               if (lcpcafret < 0) {
-                       retval = -1;
-               }
-       }
-
-       return(retval);
-}
-
-static int lc_process_conf_apache_file(const char *configfile, const char *pathprefix) {
-       LC_FILE *configfp = NULL;
-       const char *local_lc_errfile;
-       char linebuf[LC_LINEBUF_LEN] = {0}, *linebuf_ptr = NULL, *tmp_ptr = NULL;
-       char *lastsection = NULL;
-       char qualifbuf[LC_LINEBUF_LEN] = {0};
-       char *cmd = NULL, *value = NULL, *sep = NULL, *cmdend = NULL;
-       char *fgetsret = NULL;
-       int lcpvret = -1, lpcafret = -1;
-       int invalid_section = 0, ignore_section = 0;
-       int local_lc_errline;
-       int retval = 0;
-       lc_err_t save_lc_errno = LC_ERR_NONE;
-
-       if (pathprefix != NULL) {
-               /* Copy the prefix, if specified. */
-               strncpy(qualifbuf, pathprefix, sizeof(qualifbuf) - 1);
-       }
-
-       local_lc_errfile = configfile;
-       local_lc_errline = 0;
-
-       if (configfile == NULL) {
-               lc_errfile = local_lc_errfile;
-               lc_errline = local_lc_errline;
-               lc_errno = LC_ERR_INVDATA;
-               return(-1);
-       }
-
-       configfp = lc_fopen(configfile, "r");
-
-       if (configfp == NULL) {
-               lc_errfile = local_lc_errfile;
-               lc_errline = local_lc_errline;
-               lc_errno = LC_ERR_CANTOPEN;
-               return(-1);
-       }
-
-       while (1) {
-               fgetsret = lc_fgets(linebuf, sizeof(linebuf) - 1, configfp);
-               if (fgetsret == NULL) {
-                       break;
-               }
-               if (lc_feof(configfp)) {
-                       break;
-               }
-
-               local_lc_errline++;
-
-               /* Remove trailing crap (but not spaces). */
-               linebuf_ptr = &linebuf[strlen(linebuf) - 1];
-               while (*linebuf_ptr < ' ' && linebuf_ptr >= linebuf) {
-                       *linebuf_ptr = '\0';
-                       linebuf_ptr--;
-               }
-
-               /* Remove leading spaces. */
-               linebuf_ptr = &linebuf[0];
-               while (*linebuf_ptr == ' ' || *linebuf_ptr == '\t') {
-                       linebuf_ptr++;
-               }
-
-               /* Handle section header. */
-               if (linebuf_ptr[0] == '<' && linebuf_ptr[strlen(linebuf_ptr) - 1] == '>') {
-                       /* Remove < and > from around the data. */
-                       linebuf_ptr[strlen(linebuf_ptr) - 1] = '\0';
-                       linebuf_ptr++;
-
-                       /* Lowercase the command part of the section. */
-                       tmp_ptr = linebuf_ptr;
-                       while (*tmp_ptr != '\0' && *tmp_ptr != ' ') {
-                               *tmp_ptr = tolower(*tmp_ptr);
-                               tmp_ptr++;
-                       }
-
-                       /* If this is a close section command, handle it */
-                       if (linebuf_ptr[0] == '/') {
-                               linebuf_ptr++;
-                               cmd = linebuf_ptr; 
-
-                               /* Find the last section closed. */
-                               tmp_ptr = strrchr(qualifbuf, '.');
-                               if (tmp_ptr == NULL) {
-                                       lastsection = qualifbuf;
-                                       tmp_ptr = qualifbuf;
-                               } else {
-                                       lastsection = tmp_ptr + 1;
-                               }
-
-                               if (strcmp(cmd, lastsection) != 0) {
-#ifdef DEBUG
-                                       fprintf(stderr, "Section closing does not match last opened section.\n");
-                                       fprintf(stderr, "Last opened = \"%s\", Closing = \"%s\"\n", lastsection, cmd);
-#endif
-                                       retval = -1;
-                                       lc_errfile = local_lc_errfile;
-                                       lc_errline = local_lc_errline;
-                                       lc_errno = LC_ERR_BADFORMAT;
-
-                                       /* For this error, we abort immediately. */
-                                       break;
-                               }
-
-                               lcpvret = lc_process_var(qualifbuf, NULL, NULL, LC_FLAGS_SECTIONEND);
-                               if (lcpvret < 0) {
-#ifdef DEBUG
-                                       fprintf(stderr, "Invalid section terminating: \"%s\"\n", qualifbuf);
-#endif
-                               }
-
-                               /* Remove the "lastsection" part.. */
-                               *tmp_ptr = '\0';
-
-                               /* We just sucessfully closed the last section opened,
-                                  we must be in a valid section now since we only open
-                                  sections from within valid sections. */
-                               invalid_section = 0;
-                               ignore_section = 0;
-
-                               continue;
-                       }
-                       /* Otherwise, open a new section. */
-
-                       /* Don't open a section from an invalid section. */
-                       if (invalid_section == 1 || ignore_section == 1) {
-                               continue;
-                       }
-
-                       /* Parse out any argument passed. */
-                       sep = strpbrk(linebuf_ptr, " \t");
-
-                       if (sep != NULL) {
-                               cmdend = sep;
-                               /* Delete space at the end of the command. */
-                               cmdend--; /* It currently derefs to the seperator.. */
-                               while (*cmdend <= ' ') {
-                                       *cmdend = '\0';
-                                       cmdend--;
-                               }
-
-                               /* Delete the seperator char and any leading space. */
-                               *sep = '\0';
-                               sep++;
-                               while (*sep == ' ' || *sep == '\t') {
-                                       sep++;
-                               }
-                               value = sep;
-                       } else {
-                               /* XXX: should this be "" or NULL ? */
-                               value = "";
-                       }
-
-                       cmd = linebuf_ptr;
-
-                       if (qualifbuf[0] != '\0') {
-                               strncat(qualifbuf, ".", sizeof(qualifbuf) - strlen(qualifbuf) - 1);
-                       }
-                       strncat(qualifbuf, cmd, sizeof(qualifbuf) - strlen(qualifbuf) - 1);
-
-                       lcpvret = lc_process_var(qualifbuf, value, NULL, LC_FLAGS_SECTIONSTART);
-                       if (lcpvret < 0) {
-#ifdef DEBUG
-                               fprintf(stderr, "Invalid section: \"%s\"\n", qualifbuf);
-#endif
-                               invalid_section = 1;
-                               lc_errfile = local_lc_errfile;
-                               lc_errline = local_lc_errline;
-                               lc_errno = LC_ERR_INVSECTION;
-                               retval = -1;
-                       }
-                       if (lcpvret == LC_CBRET_IGNORESECTION) {
-                               ignore_section = 1;
-                       }
-                       continue;
-               }
-
-               /* Drop comments and blank lines. */
-               if (*linebuf_ptr == '#' || *linebuf_ptr == '\0') {
-                       continue;
-               }
-
-               /* Don't handle things for a section that doesn't exist. */
-               if (invalid_section == 1) {
-#ifdef DEBUG
-                       fprintf(stderr, "Ignoring line (because invalid section): %s\n", linebuf);
-#endif
-                       continue;
-               }
-               if (ignore_section == 1) {
-#ifdef DEBUG
-                       fprintf(stderr, "Ignoring line (because ignored section): %s\n", linebuf);
-#endif
-                       continue;
-               }
-
-               /* Find the command and the data in the line. */
-               sep = strpbrk(linebuf_ptr, " \t");
-               if (sep != NULL) {
-                       cmdend = sep;
-
-                       /* Delete space at the end of the command. */
-                       cmdend--; /* It currently derefs to the seperator.. */
-                       while (*cmdend <= ' ') {
-                               *cmdend = '\0';
-                               cmdend--;
-                       }
-
-                       /* Delete the seperator char and any leading space. */
-                       *sep = '\0';
-                       sep++;
-                       while (*sep == ' ' || *sep == '\t') {
-                               sep++;
-                       }
-                       value = sep;
-               } else {
-                       value = NULL;
-               }
-
-               cmd = linebuf_ptr;
-
-               /* Handle special commands. */
-               if (strcasecmp(cmd, "include") == 0) {
-                       if (value == NULL) {
-                               lc_errfile = local_lc_errfile;
-                               lc_errline = local_lc_errline;
-                               lc_errno = LC_ERR_BADFORMAT;
-                               retval = -1;
-#ifdef DEBUG
-                               fprintf(stderr, "Invalid include command.\n");
-#endif
-                               continue;
-                       }
-
-                       lpcafret = lc_process_conf_apache_include(value, qualifbuf);
-                       if (lpcafret < 0) {
-#ifdef DEBUG
-                               fprintf(stderr, "Error in included file.\n");
-#endif
-                               retval = -1;
-                       }
-                       continue;
-               }
-
-               /* Create the fully qualified variable name. */
-               if (qualifbuf[0] != '\0') {
-                       strncat(qualifbuf, ".", sizeof(qualifbuf) - strlen(qualifbuf) - 1);
-               }
-               strncat(qualifbuf, cmd, sizeof(qualifbuf) - strlen(qualifbuf) - 1);
-
-               /* Call the parent and tell them we have data. */
-               save_lc_errno = lc_errno;
-               lc_errno = LC_ERR_NONE;
-               lcpvret = lc_process_var(qualifbuf, NULL, value, LC_FLAGS_VAR);
-               if (lcpvret < 0) {
-                       if (lc_errno == LC_ERR_NONE) {
-#ifdef DEBUG
-                               fprintf(stderr, "Invalid command: \"%s\"\n", cmd);
-#endif
-                               lc_errfile = local_lc_errfile;
-                               lc_errline = local_lc_errline;
-                               lc_errno = LC_ERR_INVCMD;
-                       } else {
-#ifdef DEBUG
-                               fprintf(stderr, "Error processing command (command was valid, but an error occured, errno was set)\n");
-#endif
-                       }
-                       lc_errfile = local_lc_errfile;
-                       lc_errline = local_lc_errline;
-                       retval = -1;
-               } else {
-                       lc_errno = save_lc_errno;
-               }
-
-               /* Remove the "cmd" part of the buffer. */
-               tmp_ptr = strrchr(qualifbuf, '.');
-               if (tmp_ptr == NULL) {
-                       tmp_ptr = qualifbuf;
-               }
-               *tmp_ptr = '\0';
-       }
-
-       lc_fclose(configfp);
-
-       return(retval);
-}
-
-int lc_process_conf_apache(const char *appname, const char *configfile) {
-       return(lc_process_conf_apache_file(configfile, NULL));
-}
diff --git a/src/libconfig/conf_apache.h b/src/libconfig/conf_apache.h
deleted file mode 100644 (file)
index 36c556e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_APACHE_H
-#define LC_CONF_APACHE_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_apache(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/conf_colon.c b/src/libconfig/conf_colon.c
deleted file mode 100644 (file)
index f184309..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_colon.h"
-
-int lc_process_conf_colon(const char *appname, const char *configfile) {
-       return(-1);
-}
diff --git a/src/libconfig/conf_colon.h b/src/libconfig/conf_colon.h
deleted file mode 100644 (file)
index 7d2323c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_COLON_H
-#define LC_CONF_COLON_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_colon(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/conf_equal.c b/src/libconfig/conf_equal.c
deleted file mode 100644 (file)
index a214330..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_equal.h"
-
-int lc_process_conf_equal(const char *appname, const char *configfile) {
-       return(-1);
-}
diff --git a/src/libconfig/conf_equal.h b/src/libconfig/conf_equal.h
deleted file mode 100644 (file)
index 82e0f04..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_EQUAL_H
-#define LC_CONF_EQUAL_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_equal(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/conf_section.c b/src/libconfig/conf_section.c
deleted file mode 100644 (file)
index fb948c1..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-#include "compat.h"
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_section.h"
-
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-int lc_process_conf_section(const char *appname, const char *configfile) {
-       LC_FILE *configfp = NULL;
-       const char *local_lc_errfile;
-       char linebuf[LC_LINEBUF_LEN] = {0}, *linebuf_ptr = NULL;
-       char qualifbuf[LC_LINEBUF_LEN] = {0};
-       char *cmd = NULL, *value = NULL, *sep = NULL, *cmdend = NULL;
-       char *currsection = NULL;
-       char *fgetsret = NULL;
-       int lcpvret = -1;
-       int invalid_section = 1, ignore_section = 0;
-       int local_lc_errline;
-       int retval = 0;
-       lc_err_t save_lc_errno = LC_ERR_NONE;
-
-       local_lc_errfile = configfile;
-       local_lc_errline = 0;
-
-       if (appname == NULL || configfile == NULL) {
-               lc_errfile = local_lc_errfile;
-               lc_errline = local_lc_errline;
-               lc_errno = LC_ERR_INVDATA;
-               return(-1);
-       }
-
-       configfp = lc_fopen(configfile, "r");
-
-       if (configfp == NULL) {
-               lc_errfile = local_lc_errfile;
-               lc_errline = local_lc_errline;
-               lc_errno = LC_ERR_CANTOPEN;
-               return(-1);
-       }
-
-       while (1) {
-               fgetsret = lc_fgets(linebuf, sizeof(linebuf) - 1, configfp);
-               if (fgetsret == NULL) {
-                       break;
-               }
-               if (lc_feof(configfp)) {
-                       break;
-               }
-
-               local_lc_errline++;
-
-               /* Remove trailing crap (but not spaces). */
-               linebuf_ptr = &linebuf[strlen(linebuf) - 1];
-               while (*linebuf_ptr < ' ' && linebuf_ptr >= linebuf) {
-                       *linebuf_ptr = '\0';
-                       linebuf_ptr--;
-               }
-
-               /* Handle section header. */
-               if (linebuf[0] == '[' && linebuf[strlen(linebuf) - 1] == ']') {
-                       linebuf[strlen(linebuf) - 1] = '\0';
-                       linebuf_ptr = &linebuf[1];
-
-                       /* If a section was open, close it. */
-                       if (currsection != NULL) {
-                               lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONEND);
-                               if (lcpvret < 0) {
-#ifdef DEBUG
-                                       fprintf(stderr, "Invalid section terminating: \"%s\"\n", currsection);
-#endif
-                               }
-                               free(currsection);
-                       }
-
-                       /* Open new section. */
-                       currsection = strdup(linebuf_ptr);
-                       lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONSTART);
-                       if (lcpvret < 0) {
-#ifdef DEBUG
-                               fprintf(stderr, "Invalid section: \"%s\"\n", currsection);
-#endif
-                               invalid_section = 1;
-                               lc_errfile = local_lc_errfile;
-                               lc_errline = local_lc_errline;
-                               lc_errno = LC_ERR_INVSECTION;
-                               retval = -1;
-                       } else {
-                               invalid_section = 0;
-                               ignore_section = 0;
-                       }
-
-                       if (lcpvret == LC_CBRET_IGNORESECTION) {
-                               ignore_section = 1;
-                       }
-                       continue;
-               }
-
-               /* Remove leading spaces. */
-               linebuf_ptr = &linebuf[0];
-               while (*linebuf_ptr == ' ') {
-                       linebuf_ptr++;
-               }
-
-               /* Drop comments and blank lines. */
-               if (*linebuf_ptr == ';' || *linebuf_ptr == '\0') {
-                       continue;
-               }
-
-               /* Don't handle things for a section that doesn't exist. */
-               if (invalid_section == 1) {
-#ifdef DEBUG
-                       fprintf(stderr, "Ignoring line (because invalid section): %s\n", linebuf);
-#endif
-                       continue;
-               }
-
-               /* Don't process commands if this section is specifically ignored. */
-               if (ignore_section == 1) {
-#ifdef DEBUG
-                       fprintf(stderr, "Ignoring line (because ignored section): %s\n", linebuf);
-#endif
-                       continue;
-               }
-
-               /* Find the command and the data in the line. */
-               cmdend = sep = strpbrk(linebuf_ptr, "=");
-               if (sep == NULL) {
-#ifdef DEBUG
-                       fprintf(stderr, "Invalid line: \"%s\"\n", linebuf);
-#endif
-                       continue;
-               }
-
-               /* Delete space at the end of the command. */
-               cmdend--; /* It currently derefs to the seperator.. */
-               while (*cmdend <= ' ') {
-                       *cmdend = '\0';
-                       cmdend--;
-               }
-
-               cmd = linebuf_ptr;
-
-               /* Delete the seperator char and any leading space. */
-               *sep = '\0';
-               sep++;
-               while (*sep == ' ' || *sep == '\t') {
-                       sep++;
-               }
-               value = sep;
-
-               /* Create the fully qualified variable name. */
-               if (currsection == NULL) {
-                       strncpy(qualifbuf, cmd, sizeof(qualifbuf) - 1);
-               } else {
-                       snprintf(qualifbuf, sizeof(qualifbuf) - 1, "%s.%s", currsection, cmd);
-               }
-
-               /* Call the parent and tell them we have data. */
-               save_lc_errno = lc_errno;
-               lc_errno = LC_ERR_NONE;
-               lcpvret = lc_process_var(qualifbuf, NULL, value, LC_FLAGS_VAR);
-               if (lcpvret < 0) {
-                       if (lc_errno == LC_ERR_NONE) {
-#ifdef DEBUG
-                               fprintf(stderr, "Invalid command: \"%s\"\n", cmd);
-#endif
-                               lc_errno = LC_ERR_INVCMD;
-                       } else {
-#ifdef DEBUG
-                               fprintf(stderr, "Error processing command (command was valid, but an error occured, errno was set)\n");
-#endif
-                       }
-                       lc_errfile = local_lc_errfile;
-                       lc_errline = local_lc_errline;
-                       retval = -1;
-               } else {
-                       lc_errno = save_lc_errno;
-               }
-       }
-
-       /* Close any open section, and clean-up. */
-       if (currsection != NULL) {
-               lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONEND);
-               if (lcpvret < 0) {
-#ifdef DEBUG
-                       fprintf(stderr, "Invalid section terminating: \"%s\"\n", currsection);
-#endif
-               }
-               free(currsection);
-       }
-
-       lc_fclose(configfp);
-
-       return(retval);
-}
diff --git a/src/libconfig/conf_section.h b/src/libconfig/conf_section.h
deleted file mode 100644 (file)
index 1d1a94c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_SECTION_H
-#define LC_CONF_SECTION_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_section(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/conf_space.c b/src/libconfig/conf_space.c
deleted file mode 100644 (file)
index 50a9b23..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-#include "compat.h"
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_space.h"
-
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-int lc_process_conf_space(const char *appname, const char *configfile) {
-       LC_FILE *configfp = NULL;
-       const char *local_lc_errfile;
-       char linebuf[LC_LINEBUF_LEN] = {0}, *linebuf_ptr = NULL;
-       char *cmd = NULL, *value = NULL, *sep = NULL;
-       char *fgetsret = NULL;
-       int local_lc_errline;
-       int lcpvret = -1;
-       int retval = 0;
-       lc_err_t save_lc_errno = LC_ERR_NONE;
-
-       local_lc_errfile = configfile;
-       local_lc_errline = 0;
-
-       if (appname == NULL || configfile == NULL) {
-               lc_errfile = local_lc_errfile;
-               lc_errline = local_lc_errline;
-               lc_errno = LC_ERR_INVDATA;
-               return(-1);
-       }
-
-       configfp = lc_fopen(configfile, "r");
-
-       if (configfp == NULL) {
-               lc_errfile = local_lc_errfile;
-               lc_errline = local_lc_errline;
-               lc_errno = LC_ERR_CANTOPEN;
-               return(-1);
-       }
-
-       while (1) {
-               fgetsret = lc_fgets(linebuf, sizeof(linebuf) - 1, configfp);
-               if (fgetsret == NULL) {
-                       break;
-               }
-               if (lc_feof(configfp)) {
-                       break;
-               }
-
-               local_lc_errline++;
-
-               linebuf_ptr = &linebuf[strlen(linebuf) - 1];
-               while (*linebuf_ptr < ' ' && linebuf_ptr >= linebuf) {
-                       *linebuf_ptr = '\0';
-                       linebuf_ptr--;
-               }
-
-               linebuf_ptr = &linebuf[0];
-               while (*linebuf_ptr == ' ') {
-                       linebuf_ptr++;
-               }
-
-               if (*linebuf_ptr == '#' || *linebuf_ptr == '\0') {
-                       continue;
-               }
-
-
-               sep = strpbrk(linebuf_ptr, " \t");
-               cmd = linebuf_ptr;
-               if (sep != NULL) {
-                       *sep = '\0';
-                       sep++;
-                       while (*sep == ' ' || *sep == '\t') {
-                               sep++;
-                       }
-                       value = sep;
-               } else {
-                       value = NULL;
-               }
-
-               save_lc_errno = lc_errno;
-               lc_errno = LC_ERR_NONE;
-               lcpvret = lc_process_var(cmd, NULL, value, LC_FLAGS_VAR);
-               if (lcpvret < 0) {
-                       if (lc_errno == LC_ERR_NONE) {
-#ifdef DEBUG
-                               fprintf(stderr, "Invalid command: \"%s\"\n", cmd);
-#endif
-                               lc_errno = LC_ERR_INVCMD;
-                       } else {
-#ifdef DEBUG
-                               fprintf(stderr, "Error processing command (command was valid, but an error occured, errno was set)\n");
-#endif
-                       }
-                       lc_errfile = local_lc_errfile;
-                       lc_errline = local_lc_errline;
-                       retval = -1;
-               } else {
-                       lc_errno = save_lc_errno;
-               }
-       }
-
-       lc_fclose(configfp);
-
-       return(retval);
-}
diff --git a/src/libconfig/conf_space.h b/src/libconfig/conf_space.h
deleted file mode 100644 (file)
index 6cf0462..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_SPACE_H
-#define LC_CONF_SPACE_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_space(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/conf_xml.c b/src/libconfig/conf_xml.c
deleted file mode 100644 (file)
index 85edd51..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_xml.h"
-
-int lc_process_conf_xml(const char *appname, const char *configfile) {
-       return(-1);
-}
diff --git a/src/libconfig/conf_xml.h b/src/libconfig/conf_xml.h
deleted file mode 100644 (file)
index f0deffb..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_XML_H
-#define LC_CONF_XML_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_xml(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/libconfig.c b/src/libconfig/libconfig.c
deleted file mode 100644 (file)
index 9f80a76..0000000
+++ /dev/null
@@ -1,1073 +0,0 @@
-#include "compat.h"
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_section.h"
-#include "conf_apache.h"
-#include "conf_colon.h"
-#include "conf_equal.h"
-#include "conf_space.h"
-#include "conf_xml.h"
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-
-struct lc_varhandler_st *varhandlers = NULL;
-lc_err_t lc_errno = LC_ERR_NONE;
-const char *lc_errfile = NULL;
-int lc_optind = 0;
-int lc_errline = 0;
-
-extern char **environ;
-
-static int lc_process_var_string(void *data, const char *value, const char **endptr) {
-       char **dataval;
-
-       dataval = data;
-       *dataval = strdup(value);
-
-       *endptr = NULL;
-
-       return(0);
-}
-
-static int lc_process_var_cidr(void *data, const char *value, const char **endptr) {
-       return(-1);
-}
-
-static int lc_process_var_hostname6(void *data, const char *value, const char **endptr) {
-       return(-1);
-}
-
-static int lc_process_var_hostname4(void *data, const char *value, const char **endptr) {
-       return(-1);
-}
-
-static int lc_process_var_ip6(void *data, const char *value, const char **endptr) {
-       return(-1);
-}
-
-static int lc_process_var_ip4(void *data, const char *value, const char **endptr) {
-       uint32_t *dataval, retval = 0;
-       const char *dotptr = NULL;
-       int tmpval = -1;
-//     int dotcount
-
-       dataval = data;
-
-       dotptr = value;
-
-       while (1) {
-               tmpval = atoi(dotptr);
-               if (tmpval < 0) {
-                       break;
-               }
-
-               retval <<= 8;
-               retval |= tmpval;
-
-               dotptr = strpbrk(dotptr, "./ \t");
-               if (dotptr == NULL) {
-                       break;
-               }
-               if (*dotptr != '.') {
-                       break;
-               }
-               dotptr++;
-       }
-
-       *dataval = retval;
-
-       *endptr = (char *) dotptr;
-
-       return(0);
-}
-
-static int lc_process_var_longlong(void *data, const char *value, const char **endptr) {
-       long long *dataval;
-
-       dataval = data;
-       *dataval = strtoll(value, (char **) endptr, 10);
-
-       return(0);
-}
-
-static int lc_process_var_long(void *data, const char *value, const char **endptr) {
-       long *dataval;
-
-       dataval = data;
-       *dataval = strtoll(value, (char **) endptr, 10);
-
-       return(0);
-}
-
-static int lc_process_var_int(void *data, const char *value, const char **endptr) {
-       int *dataval;
-
-       dataval = data;
-       *dataval = strtoll(value, (char **) endptr, 10);
-
-       return(0);
-}
-
-static int lc_process_var_short(void *data, const char *value, const char **endptr) {
-       short *dataval;
-
-       dataval = data;
-       *dataval = strtoll(value, (char **) endptr, 10);
-
-       return(0);
-}
-
-static int lc_process_var_bool_byexistance(void *data, const char *value, const char **endptr) {
-       int *dataval;
-
-       dataval = data;
-
-       *dataval = 1;
-
-       *endptr = NULL;
-
-       return(0);
-}
-
-static int lc_process_var_bool(void *data, const char *value, const char **endptr) {
-       char *trueval[] = {"enable", "true", "yes", "on", "y", "1"};
-       char *falseval[] = {"disable", "false", "no", "off", "n", "0"};
-       size_t chkvallen, vallen;
-       int *dataval;
-       int i;
-
-       dataval = data;
-
-       *dataval = -1;
-
-       vallen = strlen(value);
-
-       for (i = 0; i < (sizeof(trueval) / sizeof(*trueval)); i++) {
-               chkvallen = strlen(trueval[i]);
-
-               /*
-                * Skip if there's no way we could find a match here.
-                */
-               if (chkvallen > vallen) {
-                       continue;
-               }
-
-               /*
-                * Skip if there is no partial match.
-                */
-               if (strncasecmp(value, trueval[i], chkvallen) != 0) {
-                       continue;
-               }
-
-               if (value[chkvallen] == '\0' || value[chkvallen] == ',' || \
-                   value[chkvallen] == ' ') {
-                       /* Declare a winner and set the next token. */
-                       *endptr = value + chkvallen;
-                       *dataval = 1;
-                       return(0);
-               }
-       }
-
-       for (i = 0; i < (sizeof(falseval) / sizeof(*falseval)); i++) {
-               chkvallen = strlen(falseval[i]);
-
-               /*
-                * Skip if there's no way we could find a match here.
-                */
-               if (chkvallen > vallen) {
-                       continue;
-               }
-
-               /*
-                * Skip if there is no partial match.
-                */
-               if (strncasecmp(value, falseval[i], chkvallen) != 0) {
-                       continue;
-               }
-
-               if (value[chkvallen] == '\0' || value[chkvallen] == ',' || \
-                   value[chkvallen] == ' ') {
-                       /* Declare a winner and set the next token. */
-                       *endptr = value + chkvallen;
-                       *dataval = 0;
-                       return(0);
-               }
-       }
-
-       lc_errno = LC_ERR_BADFORMAT;
-       return(-1);
-}
-
-static unsigned long long lc_process_size(const char *value, const char **endptr) {
-       unsigned long long retval = 0;
-       char *mult = NULL;
-
-       retval = strtoll(value, &mult, 10);
-       if (mult != NULL) {
-               switch (tolower(mult[0])) {
-                       case 'p':
-                               retval *= 1125899906842624LLU;
-                               break;
-                       case 't':
-                               retval *= 1958505086976LLU;
-                               break;
-                       case 'g':
-                               retval *= 1073741824;
-                               break;
-                       case 'm':
-                               retval *= 1048576;
-                               break;
-                       case 'k':
-                               retval *= 1024;
-                               break;
-                       default:
-                               break;
-               }
-       }
-
-       return(retval);
-}
-
-static int lc_process_var_sizelonglong(void *data, const char *value, const char **endptr) {
-       long long *dataval;
-
-       dataval = data;
-       *dataval = lc_process_size(value, endptr);
-
-       return(0);
-}
-
-static int lc_process_var_sizelong(void *data, const char *value, const char **endptr) {
-       long *dataval;
-
-       dataval = data;
-       *dataval = lc_process_size(value, endptr);
-
-       return(0);
-}
-
-static int lc_process_var_sizeint(void *data, const char *value, const char **endptr) {
-       int *dataval;
-
-       dataval = data;
-       *dataval = lc_process_size(value, endptr);
-
-       return(0);
-}
-
-static int lc_process_var_sizeshort(void *data, const char *value, const char **endptr) {
-       short *dataval;
-
-       dataval = data;
-       *dataval = lc_process_size(value, endptr);
-
-       return(0);
-}
-
-static int lc_process_var_sizesizet(void *data, const char *value, const char **endptr) {
-       size_t *dataval;
-
-       dataval = data;
-       *dataval = lc_process_size(value, endptr);
-
-       return(0);
-}
-
-
-static int lc_handle_type(lc_var_type_t type, const char *value, void *data) {
-       const char *next;
-       int is_list;
-
-       is_list = type & LC_VAR_LIST;
-
-       if (is_list == LC_VAR_LIST) {
-       }
-
-       switch (type) {
-               case LC_VAR_STRING:
-                       return(lc_process_var_string(data, value, &next));
-                       break;
-               case LC_VAR_LONG_LONG:
-                       return(lc_process_var_longlong(data, value, &next));
-                       break;
-               case LC_VAR_LONG:
-                       return(lc_process_var_long(data, value, &next));
-                       break;
-               case LC_VAR_INT:
-                       return(lc_process_var_int(data, value, &next));
-                       break;
-               case LC_VAR_SHORT:
-                       return(lc_process_var_short(data, value, &next));
-                       break;
-               case LC_VAR_BOOL:
-                       return(lc_process_var_bool(data, value, &next));
-                       break;
-               case LC_VAR_SIZE_LONG_LONG:
-                       return(lc_process_var_sizelonglong(data, value, &next));
-                       break;
-               case LC_VAR_SIZE_LONG:
-                       return(lc_process_var_sizelong(data, value, &next));
-                       break;
-               case LC_VAR_SIZE_INT:
-                       return(lc_process_var_sizeint(data, value, &next));
-                       break;
-               case LC_VAR_SIZE_SHORT:
-                       return(lc_process_var_sizeshort(data, value, &next));
-                       break;
-               case LC_VAR_BOOL_BY_EXISTANCE:
-                       return(lc_process_var_bool_byexistance(data, value, &next));
-                       break;
-               case LC_VAR_SIZE_SIZE_T:
-                       return(lc_process_var_sizesizet(data, value, &next));
-                       break;
-               case LC_VAR_IP:
-               case LC_VAR_IP4:
-                       return(lc_process_var_ip4(data, value, &next));
-                       break;
-               case LC_VAR_IP6:
-                       return(lc_process_var_ip6(data, value, &next));
-                       break;
-               case LC_VAR_HOSTNAME4:
-                       return(lc_process_var_hostname4(data, value, &next));
-                       break;
-               case LC_VAR_HOSTNAME6:
-                       return(lc_process_var_hostname6(data, value, &next));
-                       break;
-               case LC_VAR_CIDR:
-                       return(lc_process_var_cidr(data, value, &next));
-                       break;
-               case LC_VAR_TIME:
-               case LC_VAR_DATE:
-               case LC_VAR_FILENAME:
-               case LC_VAR_DIRECTORY:
-#ifdef DEBUG
-                       fprintf(stderr, "Not implemented yet!\n");
-#endif
-                       return(-1);
-               case LC_VAR_NONE:
-               case LC_VAR_UNKNOWN:
-               case LC_VAR_SECTION:
-               case LC_VAR_SECTIONSTART:
-               case LC_VAR_SECTIONEND:
-                       return(0);
-                       break;
-       }
-
-       return(-1);
-}
-
-static int lc_handle(struct lc_varhandler_st *handler, const char *var, const char *varargs, const char *value, lc_flags_t flags) {
-       const char *localvar = NULL;
-       int retval;
-
-       if (var != NULL) {
-               localvar = strrchr(var, '.');
-               if (localvar == NULL) {
-                       localvar = var;
-               } else {
-                       localvar++;
-               }
-       } else {
-               localvar = NULL;
-       }
-
-       switch (handler->mode) {
-               case LC_MODE_CALLBACK:
-                       if (handler->callback != NULL) {
-                               retval = handler->callback(localvar, var, varargs, value, flags, handler->extra);
-                               if (retval < 0) {
-                                       lc_errno = LC_ERR_CALLBACK;
-                               }
-                               return(retval);
-                       }
-                       break;
-               case LC_MODE_VAR:
-                       return(lc_handle_type(handler->type, value, handler->data));
-                       break;
-       }
-
-       return(-1);
-}
-
-static int lc_process_environment(const char *appname) {
-#ifndef ENABLE_SMALL
-       struct lc_varhandler_st *handler = NULL;
-       size_t appnamelen = 0;
-       char varnamebuf[128] = {0};
-       char **currvar;
-       char *sep = NULL, *value = NULL, *cmd = NULL;
-       char *ucase_appname = NULL, *ucase_appname_itr = NULL;
-       char *lastcomponent_handler = NULL;
-       int varnamelen = 0;
-       char *local_lc_errfile;
-       int local_lc_errline;
-
-       /* Make sure we have an environment to screw with, if not,
-          no arguments were found to be in error */
-       if (environ == NULL || appname == NULL) {
-               return(0);
-       }
-
-       local_lc_errfile = "<environment>";
-       local_lc_errline = 0;
-
-       /* Allocate and create our uppercase appname. */
-       ucase_appname = strdup(appname);
-       if (ucase_appname == NULL) {
-               lc_errfile = local_lc_errfile;
-               lc_errline = local_lc_errline;
-               lc_errno = LC_ERR_ENOMEM;
-               return(-1);
-       }
-       for (ucase_appname_itr = ucase_appname; *ucase_appname_itr != '\0'; ucase_appname_itr++) {
-               *ucase_appname_itr = toupper(*ucase_appname_itr);
-       }
-
-       appnamelen = strlen(ucase_appname);
-
-       for (currvar = environ; *currvar != NULL; currvar++) {
-               /* If it doesn't begin with our appname ignore it completely. */
-               if (strncmp(*currvar, ucase_appname, appnamelen) != 0) {
-                       continue;
-               }
-
-               /* Find our seperator. */
-               sep = strchr(*currvar, '=');
-               if (sep == NULL) {
-                       continue;
-               }
-
-               varnamelen = sep - *currvar;
-
-               /* Skip variables that would overflow our buffer. */
-               if (varnamelen >= sizeof(varnamebuf)) {
-                       continue;
-               }
-
-               strncpy(varnamebuf, *currvar, varnamelen);
-
-               varnamebuf[varnamelen] = '\0';
-               value = sep + 1;
-
-               /* We ignore APPNAME by itself. */
-               if (strlen(varnamebuf) <= appnamelen) {
-                       continue;
-               }
-
-               /* Further it must be <APPNAME>_ */
-               if (varnamebuf[appnamelen] != '_') {
-                       continue;
-               }
-
-               cmd = varnamebuf + appnamelen + 1;
-
-               /* We don't allow section specifiers, for reasons see notes in
-                  the cmdline processor (below). */
-               if (strchr(cmd, '.') != NULL) {
-                       continue;
-               }
-
-               for (handler = varhandlers; handler != NULL; handler = handler->_next) {
-                       if (handler->var == NULL) {
-                               continue;
-                       }
-
-                       /* Skip handlers which don't agree with being
-                          processed outside a config file */
-                       if (handler->type == LC_VAR_SECTION ||
-                           handler->type == LC_VAR_SECTIONSTART ||
-                           handler->type == LC_VAR_SECTIONEND ||
-                           handler->type == LC_VAR_UNKNOWN) {
-                               continue;
-                       }
-
-                       /* Find the last part of the variable and compare it with 
-                          the option being processed, if a wildcard is given. */
-                       if (handler->var[0] == '*' && handler->var[1] == '.') {
-                               lastcomponent_handler = strrchr(handler->var, '.');
-                               if (lastcomponent_handler == NULL) {
-                                       lastcomponent_handler = handler->var;
-                               } else {
-                                       lastcomponent_handler++;
-                               }
-                       } else {
-                               lastcomponent_handler = handler->var;
-                       }
-
-                       /* Ignore this handler if they don't match. */
-                       if (strcasecmp(lastcomponent_handler, cmd) != 0) {
-                               continue;
-                       }
-
-                       if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) {
-                               value = NULL;
-                       }
-
-                       /* We ignore errors from the environment variables,
-                          they're mostly insignificant. */
-                       lc_handle(handler, cmd, NULL, value, LC_FLAGS_ENVIRON);
-
-                       break;
-               }
-       }
-
-       free(ucase_appname);
-
-#endif
-       return(0);
-}
-
-static int lc_process_cmdline(int argc, char **argv) {
-       struct lc_varhandler_st *handler = NULL;
-       char *cmdarg = NULL, *cmdoptarg = NULL;
-       char *lastcomponent_handler = NULL;
-       char **newargv = NULL;
-       char *usedargv = NULL;
-       int cmdargidx = 0;
-       int newargvidx = 0;
-       int retval = 0, chkretval = 0;
-       int ch = 0;
-       char *local_lc_errfile;
-       int local_lc_errline;
-
-       local_lc_errfile = "<cmdline>";
-       local_lc_errline = 0;
-
-       /* Allocate "argc + 1" (+1 for the NULL terminator) elements. */
-       newargv = malloc((argc + 1) * sizeof(*newargv));
-       if (newargv == NULL) {
-               lc_errfile = local_lc_errfile;
-               lc_errline = local_lc_errline;
-               lc_errno = LC_ERR_ENOMEM;
-               return(-1);
-       }
-       newargv[newargvidx++] = argv[0];
-       newargv[argc] = NULL;
-
-       /* Allocate space to indicate which arguments have been used. */
-       usedargv = malloc(argc * sizeof(*usedargv));
-       if (usedargv == NULL) {
-               lc_errfile = local_lc_errfile;
-               lc_errline = local_lc_errline;
-               lc_errno = LC_ERR_ENOMEM;
-               free(newargv);
-               return(-1);
-       }
-       for (cmdargidx = 0; cmdargidx < argc; cmdargidx++) {
-               usedargv[cmdargidx] = 0;
-       }
-
-       for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) {
-               cmdarg = argv[cmdargidx];
-
-               /* Make sure we have an argument here. */
-               if (cmdarg == NULL) {
-                       break;
-               }
-
-               /* If the argument isn't an option, skip. */
-               if (cmdarg[0] != '-') {
-                       continue;
-               }
-
-               /* Setup a pointer in the new array for the actual argument. */
-               newargv[newargvidx++] = cmdarg;
-               usedargv[cmdargidx] = 1;
-
-               /* Then shift the argument past the '-' so we can ignore it. */
-               cmdarg++;
-
-               /* Handle long options. */
-               if (cmdarg[0] == '-') {
-                       cmdarg++;
-
-                       /* Don't process arguments after the '--' option. */
-                       if (cmdarg[0] == '\0') {
-                               break;
-                       }
-
-                       /* Look for a variable name that matches */
-                       for (handler = varhandlers; handler != NULL; handler = handler->_next) {
-                               /* Skip handlers with no variable name. */
-                               if (handler->var == NULL) {
-                                       continue;
-                               }
-                               /* Skip handlers which don't agree with being
-                                  processed on the command line. */
-                               if (handler->type == LC_VAR_SECTION ||
-                                   handler->type == LC_VAR_SECTIONSTART ||
-                                   handler->type == LC_VAR_SECTIONEND ||
-                                   handler->type == LC_VAR_UNKNOWN) {
-                                       continue;
-                               }
-
-                               /* Find the last part of the variable and compare it with 
-                                  the option being processed, if a wildcard is given. */
-                               if (handler->var[0] == '*' && handler->var[1] == '.') {
-                                       lastcomponent_handler = strrchr(handler->var, '.');
-                                       if (lastcomponent_handler == NULL) {
-                                               lastcomponent_handler = handler->var;
-                                       } else {
-                                               lastcomponent_handler++;
-                                       }
-                               } else {
-                                       /* Disallow use of the fully qualified name
-                                          since there was no sectionstart portion
-                                          we cannot allow it to handle children of it. */
-                                       if (strchr(cmdarg, '.') != NULL) {
-                                               continue;
-                                       }
-                                       lastcomponent_handler = handler->var;
-                               }
-
-                               /* Ignore this handler if they don't match. */
-                               if (strcasecmp(lastcomponent_handler, cmdarg) != 0) {
-                                       continue;
-                               }
-
-                               if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) {
-                                       cmdoptarg = NULL;
-                               } else {
-                                       cmdargidx++;
-                                       if (cmdargidx >= argc) {
-                                               fprintf(stderr, "Argument required.\n");
-                                               lc_errfile = local_lc_errfile;
-                                               lc_errline = local_lc_errline;
-                                               lc_errno = LC_ERR_BADFORMAT;
-                                               free(usedargv);
-                                               free(newargv);
-                                               return(-1);
-                                       }
-                                       cmdoptarg = argv[cmdargidx];
-                                       newargv[newargvidx++] = cmdoptarg;
-                                       usedargv[cmdargidx] = 1;
-                               }
-
-                               chkretval = lc_handle(handler, handler->var, NULL, cmdoptarg, LC_FLAGS_CMDLINE);
-                               if (chkretval < 0) {
-                                       retval = -1;
-                               }
-
-                               break;
-                       }
-
-                       if (handler == NULL) {
-                               fprintf(stderr, "Unknown option: --%s\n", cmdarg);
-                               lc_errfile = local_lc_errfile;
-                               lc_errline = local_lc_errline;
-                               lc_errno = LC_ERR_INVCMD;
-                               free(usedargv);
-                               free(newargv);
-                               return(-1);
-                       }
-               } else {
-                       for (; *cmdarg != '\0'; cmdarg++) {
-                               ch = *cmdarg;
-
-                               for (handler = varhandlers; handler != NULL; handler = handler->_next) {
-                                       if (handler->opt != ch || handler->opt == '\0') {
-                                               continue;
-                                       }
-                                       /* Skip handlers which don't agree with being
-                                          processed on the command line. */
-                                       if (handler->type == LC_VAR_SECTION ||
-                                           handler->type == LC_VAR_SECTIONSTART ||
-                                           handler->type == LC_VAR_SECTIONEND ||
-                                           handler->type == LC_VAR_UNKNOWN) {
-                                               continue;
-                                       }
-
-                                       if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) {
-                                               cmdoptarg = NULL;
-                                       } else {
-                                               cmdargidx++;
-                                               if (cmdargidx >= argc) {
-                                                       fprintf(stderr, "Argument required.\n");
-                                                       lc_errfile = local_lc_errfile;
-                                                       lc_errline = local_lc_errline;
-                                                       lc_errno = LC_ERR_BADFORMAT;
-                                                       free(usedargv);
-                                                       free(newargv);
-                                                       return(-1);
-                                               }
-                                               cmdoptarg = argv[cmdargidx];
-                                               newargv[newargvidx++] = cmdoptarg;
-                                               usedargv[cmdargidx] = 1;
-                                       }
-
-                                       chkretval = lc_handle(handler, handler->var, NULL, cmdoptarg, LC_FLAGS_CMDLINE);
-                                       if (chkretval < 0) {
-                                               lc_errfile = local_lc_errfile;
-                                               lc_errline = local_lc_errline;
-                                               retval = -1;
-                                       }
-
-                                       break;
-                               }
-
-                               if (handler == NULL) {
-                                       fprintf(stderr, "Unknown option: -%c\n", ch);
-                                       lc_errfile = local_lc_errfile;
-                                       lc_errline = local_lc_errline;
-                                       lc_errno = LC_ERR_INVCMD;
-                                       free(usedargv);
-                                       free(newargv);
-                                       return(-1);
-                               }
-                       }
-               }
-       }
-
-       if (retval >= 0) {
-               lc_optind = newargvidx;
-               for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) {
-                       if (usedargv[cmdargidx] != 0) {
-                               continue;
-                       }
-                       
-                       cmdarg = argv[cmdargidx];
-
-                       newargv[newargvidx++] = cmdarg;
-               }
-               for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) {
-                       argv[cmdargidx] = newargv[cmdargidx];
-               }
-       }
-
-       free(usedargv);
-       free(newargv);
-
-       return(retval);
-}
-
-
-int lc_process_var(const char *var, const char *varargs, const char *value, lc_flags_t flags) {
-       struct lc_varhandler_st *handler = NULL;
-       const char *lastcomponent_handler = NULL, *lastcomponent_var = NULL;
-
-       lastcomponent_var = strrchr(var, '.');
-       if (lastcomponent_var == NULL) {
-               lastcomponent_var = var;
-       } else {
-               lastcomponent_var++;
-       }
-
-       for (handler = varhandlers; handler != NULL; handler = handler->_next) {
-               /* If either handler->var or var is NULL, skip, unless both are NULL. */
-               if (handler->var != var && (handler->var == NULL || var == NULL)) {
-                       continue;
-               }
-
-               /* If both are not-NULL, compare them. */
-               if (handler->var != NULL) {
-                       /* Wild-card-ish match. */
-                       if (handler->var[0] == '*' && handler->var[1] == '.') {
-                               /* Only compare the last components */
-
-                               lastcomponent_handler = strrchr(handler->var, '.') + 1; /* strrchr() won't return NULL, because we already checked it. */
-
-                               if (strcasecmp(lastcomponent_handler, lastcomponent_var) != 0) {
-                                       continue;
-                               }
-                       } else if (strcasecmp(handler->var, var) != 0) {
-                               /* Exact (case-insensitive comparison) failed. */
-                               continue;
-                       }
-               }
-
-               if (value == NULL &&
-                   handler->type != LC_VAR_NONE &&
-                   handler->type != LC_VAR_BOOL_BY_EXISTANCE &&
-                   handler->type != LC_VAR_SECTION &&
-                   handler->type != LC_VAR_SECTIONSTART &&
-                   handler->type != LC_VAR_SECTIONEND) {
-                       lc_errno = LC_ERR_BADFORMAT;
-                       break;
-               }
-
-               return(lc_handle(handler, var, varargs, value, flags));
-       }
-
-       return(-1);
-}
-
-int lc_register_callback(const char *var, char opt, lc_var_type_t type, int (*callback)(const char *, const char *, const char *, const char *, lc_flags_t, void *), void *extra) {
-       struct lc_varhandler_st *newhandler = NULL;
-
-       newhandler = malloc(sizeof(*newhandler));
-
-       if (newhandler == NULL) {
-               return(-1);
-       }
-
-       if (var == NULL) {
-               newhandler->var = NULL;
-       } else {
-               newhandler->var = strdup(var);
-       }
-       newhandler->mode = LC_MODE_CALLBACK;
-       newhandler->type = type;
-       newhandler->callback = callback;
-       newhandler->opt = opt;
-       newhandler->extra = extra;
-       newhandler->_next = varhandlers;
-
-       varhandlers = newhandler;
-
-       return(0);
-}
-
-int lc_register_var(const char *var, lc_var_type_t type, void *data, char opt) {
-       struct lc_varhandler_st *newhandler = NULL;
-
-       newhandler = malloc(sizeof(*newhandler));
-
-       if (newhandler == NULL) {
-               return(-1);
-       }
-
-       if (var == NULL) {
-               newhandler->var = NULL;
-       } else {
-               newhandler->var = strdup(var);
-       }
-       newhandler->mode = LC_MODE_VAR;
-       newhandler->type = type;
-       newhandler->data = data;
-       newhandler->opt = opt;
-       newhandler->extra = NULL;
-       newhandler->_next = varhandlers;
-
-       varhandlers = newhandler;
-
-       return(0);
-}
-
-int lc_process_file(const char *appname, const char *pathname, lc_conf_type_t type) {
-       int chkretval = 0;
-
-       switch (type) {
-               case LC_CONF_SECTION:
-                       chkretval = lc_process_conf_section(appname, pathname);
-                       break;
-               case LC_CONF_APACHE:
-                       chkretval = lc_process_conf_apache(appname, pathname);
-                       break;
-               case LC_CONF_COLON:
-                       chkretval = lc_process_conf_colon(appname, pathname);
-                       break;
-               case LC_CONF_EQUAL:
-                       chkretval = lc_process_conf_equal(appname, pathname);
-                       break;
-               case LC_CONF_SPACE:
-                       chkretval = lc_process_conf_space(appname, pathname);
-                       break;
-               case LC_CONF_XML:
-                       chkretval = lc_process_conf_xml(appname, pathname);
-                       break;
-               default:
-                       chkretval = -1;
-                       lc_errno = LC_ERR_INVDATA;
-                       break;
-       }
-
-       return(chkretval);
-}
-
-static int lc_process_files(const char *appname, lc_conf_type_t type, const char *extraconfig) {
-#ifdef HAVE_GETPWUID
-       struct passwd *pwinfo = NULL;
-#endif
-       char configfiles[3][13][512] = {{{0}}};
-       char *configfile = NULL;
-       char *homedir = NULL;
-       int configsetidx = 0, configidx = 0;
-       int chkretval = 0, retval = 0;
-
-       if (extraconfig != NULL) {
-               snprintf(configfiles[0][0], sizeof(**configfiles) - 1, "%s", extraconfig);
-       }
-       snprintf(configfiles[1][0], sizeof(**configfiles) - 1, "/etc/%s.cfg", appname);
-       snprintf(configfiles[1][1], sizeof(**configfiles) - 1, "/etc/%s.conf", appname);
-       snprintf(configfiles[1][2], sizeof(**configfiles) - 1, "/etc/%s/%s.cfg", appname, appname);
-       snprintf(configfiles[1][3], sizeof(**configfiles) - 1, "/etc/%s/%s.conf", appname, appname);
-       snprintf(configfiles[1][4], sizeof(**configfiles) - 1, "/usr/etc/%s.cfg", appname);
-       snprintf(configfiles[1][5], sizeof(**configfiles) - 1, "/usr/etc/%s.conf", appname);
-       snprintf(configfiles[1][6], sizeof(**configfiles) - 1, "/usr/etc/%s/%s.cfg", appname, appname);
-       snprintf(configfiles[1][7], sizeof(**configfiles) - 1, "/usr/etc/%s/%s.conf", appname, appname);
-       snprintf(configfiles[1][8], sizeof(**configfiles) - 1, "/usr/local/etc/%s.cfg", appname);
-       snprintf(configfiles[1][9], sizeof(**configfiles) - 1, "/usr/local/etc/%s.conf", appname);
-       snprintf(configfiles[1][10], sizeof(**configfiles) - 1, "/usr/local/etc/%s/%s.cfg", appname, appname);
-       snprintf(configfiles[1][11], sizeof(**configfiles) - 1, "/usr/local/etc/%s/%s.conf", appname, appname);
-       if (getuid() != 0) {
-               homedir = getenv("HOME");
-#ifdef HAVE_GETPWUID
-               if (homedir == NULL) {
-                       pwinfo = getpwuid(getuid());
-                       if (pwinfo != NULL) {
-                               homedir = pwinfo->pw_dir;
-                       }
-               }
-#endif
-               if (homedir != NULL) {
-                       if (strcmp(homedir, "/") != 0 && access(homedir, R_OK|W_OK|X_OK) == 0) {
-                               snprintf(configfiles[2][0], sizeof(**configfiles) - 1, "%s/.%src", homedir, appname);
-                               snprintf(configfiles[2][1], sizeof(**configfiles) - 1, "%s/.%s.cfg", homedir, appname);
-                               snprintf(configfiles[2][2], sizeof(**configfiles) - 1, "%s/.%s.conf", homedir, appname);
-                               snprintf(configfiles[2][3], sizeof(**configfiles) - 1, "%s/.%s/%s.cfg", homedir, appname, appname);
-                               snprintf(configfiles[2][4], sizeof(**configfiles) - 1, "%s/.%s/%s.conf", homedir, appname, appname);
-                               snprintf(configfiles[2][5], sizeof(**configfiles) - 1, "%s/.%s/config", homedir, appname);
-                       }
-               }
-       }
-
-       for (configsetidx = 0; configsetidx < 3; configsetidx++) {
-               for (configidx = 0; configidx < 13; configidx++) {
-                       configfile = configfiles[configsetidx][configidx];
-                       if (configfile[0] == '\0') {
-                               break;
-                       }
-                       if (access(configfile, R_OK) == 0) {
-                               chkretval = lc_process_file(appname, configfile, type);
-                               if (chkretval < 0) {
-                                       retval = -1;
-                               }
-                               break;
-                       }
-               }
-       }
-
-       return(retval);
-}
-
-void lc_cleanup(void) {
-       struct lc_varhandler_st *handler = NULL, *next = NULL;
-
-       handler = varhandlers;
-       while (handler != NULL) {
-               if (handler->var != NULL) {
-                       free(handler->var);
-               }
-
-               next = handler->_next;
-
-               free(handler);
-
-               handler = next;
-       }
-
-       varhandlers = NULL;
-
-       return;
-}
-
-int lc_process(int argc, char **argv, const char *appname, lc_conf_type_t type, const char *extra) {
-       int retval = 0, chkretval = 0;
-
-       /* Handle config files. */
-       chkretval = lc_process_files(appname, type, extra);
-       if (chkretval < 0) {
-               retval = -1;
-       }
-
-       /* Handle environment variables.*/
-       chkretval = lc_process_environment(appname);
-       if (chkretval < 0) {
-               retval = -1;
-       }
-
-       /* Handle command line arguments */
-       chkretval = lc_process_cmdline(argc, argv);
-       if (chkretval < 0) {
-               retval = -1;
-       }
-
-       return(retval);
-}
-
-
-lc_err_t lc_geterrno(void) {
-       lc_err_t retval;
-
-       retval = lc_errno;
-
-       lc_errno = LC_ERR_NONE;
-
-       return(retval);
-}
-
-char *lc_geterrstr(void) {
-       static char retval[512];
-       char *errmsg = NULL;
-
-       switch (lc_errno) {
-               case LC_ERR_NONE:
-                       errmsg = "Success";
-                       break;
-               case LC_ERR_INVCMD:
-                       errmsg = "Invalid command or option";
-                       break;
-               case LC_ERR_INVSECTION:
-                       errmsg = "Invalid section";
-                       break;
-               case LC_ERR_INVDATA:
-                       errmsg = "Invalid application data (internal error)";
-                       break;
-               case LC_ERR_BADFORMAT:
-                       errmsg = "Bad data specified or incorrect format.";
-                       break;
-               case LC_ERR_CANTOPEN:
-                       errmsg = "Can't open file.";
-                       break;
-               case LC_ERR_CALLBACK:
-                       errmsg = "Error return from application handler.";
-                       break;
-               case LC_ERR_ENOMEM:
-                       errmsg = "Insuffcient memory.";
-                       break;
-       }
-
-       /*
-        * This is not part of the switch statement so we will get warnings
-        * about unhandled enum values.
-        */
-       if (errmsg == NULL) {
-               errmsg = "Unknown error";
-       }
-
-       if (lc_errfile == NULL) {
-               snprintf(retval, sizeof(retval), "%s:%i: %s", "<no file>", lc_errline, errmsg);
-       } else {
-               snprintf(retval, sizeof(retval), "%s:%i: %s", lc_errfile, lc_errline, errmsg);
-       }
-
-       retval[sizeof(retval) - 1] = '\0';
-
-       return(retval);
-}
diff --git a/src/libconfig/libconfig.h b/src/libconfig/libconfig.h
deleted file mode 100644 (file)
index 8c2f361..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#  ifndef _RSK_LIBCONFIG_H
-#  define _RSK_LIBCONFIG_H
-#  ifdef __cplusplus
-extern "C" {
-#  endif
-
-#  define LC_VAR_LIST 0x80
-
-typedef enum {
-        LC_CONF_SECTION,
-        LC_CONF_APACHE,
-        LC_CONF_COLON,
-        LC_CONF_EQUAL,
-        LC_CONF_SPACE,
-        LC_CONF_XML
-} lc_conf_type_t;
-
-typedef enum {
-        LC_VAR_UNKNOWN,
-        LC_VAR_NONE,
-        LC_VAR_STRING,
-        LC_VAR_LONG_LONG,
-        LC_VAR_LONG,
-        LC_VAR_INT,
-        LC_VAR_SHORT,
-        LC_VAR_BOOL,
-        LC_VAR_FILENAME,
-        LC_VAR_DIRECTORY,
-        LC_VAR_SIZE_LONG_LONG,
-        LC_VAR_SIZE_LONG,
-        LC_VAR_SIZE_INT,
-        LC_VAR_SIZE_SHORT,
-        LC_VAR_TIME,
-        LC_VAR_DATE,
-        LC_VAR_SECTION,
-        LC_VAR_SECTIONSTART,
-        LC_VAR_SECTIONEND,
-        LC_VAR_BOOL_BY_EXISTANCE,
-        LC_VAR_SIZE_SIZE_T,
-        LC_VAR_CIDR,
-        LC_VAR_IP,
-        LC_VAR_IP4,
-        LC_VAR_IP6,
-        LC_VAR_HOSTNAME4,
-        LC_VAR_HOSTNAME6,
-} lc_var_type_t;
-
-typedef enum {
-        LC_FLAGS_VAR,
-        LC_FLAGS_CMDLINE,
-        LC_FLAGS_ENVIRON,
-        LC_FLAGS_SECTIONSTART,
-        LC_FLAGS_SECTIONEND
-} lc_flags_t;
-
-typedef enum {
-        LC_ERR_NONE,
-        LC_ERR_INVCMD,
-        LC_ERR_INVSECTION,
-        LC_ERR_INVDATA,
-        LC_ERR_BADFORMAT,
-        LC_ERR_CANTOPEN,
-        LC_ERR_CALLBACK,
-        LC_ERR_ENOMEM
-} lc_err_t;
-
-int lc_process(int argc, char **argv, const char *appname, lc_conf_type_t type, const char *extra);
-int lc_register_callback(const char *var, char opt, lc_var_type_t type, int (*callback)(const char *, const char *, const char *, const char *, lc_flags_t, void *), void *extra);
-int lc_register_var(const char *var, lc_var_type_t type, void *data, char opt);
-lc_err_t lc_geterrno(void);
-char *lc_geterrstr(void);
-int lc_process_file(const char *appname, const char *pathname, lc_conf_type_t type);
-void lc_cleanup(void);
-
-#  define LC_CBRET_IGNORESECTION (255)
-#  define LC_CBRET_OKAY (0)
-#  define LC_CBRET_ERROR (-1)
-
-extern int lc_optind;
-
-#  ifdef __cplusplus
-}
-#  endif
-#  endif
diff --git a/src/libconfig/libconfig_private.h b/src/libconfig/libconfig_private.h
deleted file mode 100644 (file)
index 8310a85..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef _RSK_LIBCONFIG_PRIVATE_H
-#define _RSK_LIBCONFIG_PRIVATE_H
-
-#include "libconfig.h"
-
-extern lc_err_t lc_errno;
-extern int lc_errline;
-extern const char *lc_errfile;
-
-int lc_process_var(const char *var, const char *varargs, const char *value, lc_flags_t flags);
-
-struct lc_varhandler_st;
-
-struct lc_varhandler_st {
-       struct lc_varhandler_st *_next;
-       char *var;
-       char opt;
-       lc_var_type_t type;
-       enum {
-               LC_MODE_CALLBACK,
-               LC_MODE_VAR
-       } mode;
-       int (*callback)();
-       void *data;
-       void *extra;
-};
-
-#endif
diff --git a/src/libconfig/test-lc.c b/src/libconfig/test-lc.c
deleted file mode 100644 (file)
index ed492d8..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#include "compat.h"
-#include "libconfig.h"
-
-int help_cmd(const char *partarg, const char *arg, const char *argarg, const char *val, lc_flags_t flags, void *extra) {
-       printf("Usage info goes here\n");
-       printf("\n");
-
-       exit(EXIT_FAILURE);
-}
-int sally_cmd(const char *partarg, const char *arg, const char *argarg, const char *val, lc_flags_t flags, void *extra) {
-       fprintf(stderr, "%s sets value: \"%s\" (flags=%i)\n", arg, val, flags);
-       return(0);
-}
-
-int cmd_ifmodule(const char *partarg, const char *arg, const char *argarg, const char *val, lc_flags_t flags, void *extra) {
-       if (flags == LC_FLAGS_SECTIONEND) {
-               return(LC_CBRET_OKAY);
-       }
-       if (flags != LC_FLAGS_SECTIONSTART) {
-               fprintf(stderr, "IfModule can only be used as a section.\n");
-               return(LC_CBRET_ERROR);
-       }
-       if (argarg == NULL) {
-               fprintf(stderr, "You must specify an argument to IfModule.\n");
-               return(LC_CBRET_ERROR);
-       }
-
-       fprintf(stderr, "IfModule (%s)\n", argarg);
-       return(LC_CBRET_IGNORESECTION);
-}
-
-int main(int argc, char **argv) {
-       char *joeval = NULL;
-       size_t xval = -1;
-       int onoff = -1;
-       int lcpret = -1;
-       int i = 0;
-       int onoff2 = 0;
-       uint32_t ipaddr = 0;
-
-       lc_register_var("Section", LC_VAR_SECTION, NULL, 0);
-       lc_register_var("Somesection", LC_VAR_SECTION, NULL, 0);
-       lc_register_var("Section.Test", LC_VAR_STRING, &joeval, 'j');
-       lc_register_var("bob", LC_VAR_SIZE_SIZE_T, &xval, 's');
-       lc_register_var("Somesection.Free", LC_VAR_BOOL, &onoff, 0);
-       lc_register_var("long", LC_VAR_BOOL_BY_EXISTANCE, &onoff2, 'l');
-       lc_register_var("ipaddr", LC_VAR_IP, &ipaddr, 'i');
-       lc_register_callback("sally", 0, LC_VAR_STRING, sally_cmd, NULL);
-       lc_register_callback("HELP", 'h', LC_VAR_NONE, help_cmd, NULL);
-       lc_register_callback("*.ifmodule", 0, LC_VAR_NONE, cmd_ifmodule, NULL);
-       lcpret = lc_process_file("testapp", "build/test.conf", LC_CONF_APACHE);
-       if (lcpret < 0) {
-               fprintf(stderr, "Error processing config file: %s\n", lc_geterrstr());
-               return(EXIT_FAILURE);
-       }
-
-       lcpret = lc_process(argc, argv, "testapp", LC_CONF_APACHE, "test.cfg");
-       if (lcpret < 0) {
-               fprintf(stderr, "Error processing config file: %s\n", lc_geterrstr());
-               return(EXIT_FAILURE);
-       }
-
-       lc_cleanup();
-
-       if (joeval != NULL) {
-               fprintf(stderr, "joeval = \"%s\"\n", joeval);
-       } else {
-               fprintf(stderr, "joeval = \"(null)\"\n");
-       }
-       fprintf(stderr, "xval = %llu\n", (unsigned long long) xval);
-       fprintf(stderr, "onoff = %i\n", onoff);
-       fprintf(stderr, "long = %i\n", onoff2);
-       fprintf(stderr, "ip = %08lx\n", (unsigned long) ipaddr);
-       for (i = lc_optind; i < argc; i++) {
-               fprintf(stderr, "argv[%i] = \"%s\"\n", i, argv[i]);
-       }
-
-       return(0);
-}
diff --git a/src/libconfig/win32.h b/src/libconfig/win32.h
deleted file mode 100644 (file)
index 06f3a0d..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#if !defined(_LOCAL_WIN32_H) && defined(__WIN32__) && !defined(__CYGWIN__)
-#define _LOCAL_WIN32_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef __MINGW32__
-     /* MingW32 specific stuff here. */
-#  if defined(HAVE_WINSOCK2_H) && defined(HAVE_LIBWSOCK32)
-     /* We have to override the detected configuration
-        because it can't detect the network libraries. */
-#    define HAVE_GETHOSTBYNAME 1
-#    define HAVE_INET_ADDR 1
-#    define HAVE_SOCKET 1
-#  endif
-#  define sleep(x) Sleep((x) * 1000)
-#else
-   /* MSVC++ configuration follows */
-#  undef HAVE_UNISTD_H
-#  define HAVE_STDLIB_H 1
-#  define HAVE_WINDOWS_H 1
-#  define HAVE_STDARG_H 1
-#  define HAVE_WINSVC_H 1
-#  define HAVE_WINSOCK2_H 1
-#  define HAVE_WINDOWSX_H 1
-#endif /* __MINGW32__ */
-
-#ifdef HAVE_WINDOWS_H
-#  include <windows.h>
-#endif
-#ifdef HAVE_WINDOWSX_H
-#  include <windowsx.h>
-#endif
-#ifdef HAVE_WINSOCK2_H
-#  include <winsock2.h>
-#endif
-#ifdef HAVE_WINSVC_H
-#  include <winsvc.h>
-#endif
-
-#define _USE_WIN32_ 1
-
-#endif /* _LOCAL_WIN32_H */
diff --git a/src/liboconfig/AUTHORS b/src/liboconfig/AUTHORS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/liboconfig/COPYING b/src/liboconfig/COPYING
new file mode 100644 (file)
index 0000000..623b625
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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.
+\f
+                   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.)
+\f
+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.
+\f
+  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.
+\f
+  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
+\f
+           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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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) year  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.
+
+  <signature of Ty Coon>, 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.
diff --git a/src/liboconfig/ChangeLog b/src/liboconfig/ChangeLog
new file mode 100644 (file)
index 0000000..390c507
--- /dev/null
@@ -0,0 +1,5 @@
+2007-02-15, Version 0.1.1
+       * src/parser.y: Fixes a memory leak.
+
+2007-02-11, Version 0.1.0
+       * Initial release.
diff --git a/src/liboconfig/Makefile.am b/src/liboconfig/Makefile.am
new file mode 100644 (file)
index 0000000..4e8d086
--- /dev/null
@@ -0,0 +1,11 @@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+BUILT_SOURCES = parser.h
+CLEANFILES = parser.[ch] scanner.c
+AM_YFLAGS = -d
+
+include_HEADERS = oconfig.h
+lib_LTLIBRARIES = liboconfig.la
+
+liboconfig_la_LDFLAGS = -version-info 0:0:0 $(LEXLIB)
+liboconfig_la_SOURCES = oconfig.c oconfig.h scanner.l parser.y
diff --git a/src/liboconfig/aux_types.h b/src/liboconfig/aux_types.h
new file mode 100644 (file)
index 0000000..25b81ab
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef AUX_TYPES_H
+#define AUX_TYPES_H 1
+
+struct statement_list_s
+{
+       oconfig_item_t *statement;
+       int             statement_num;
+};
+typedef struct statement_list_s statement_list_t;
+
+struct argument_list_s
+{
+       oconfig_value_t *argument;
+       int              argument_num;
+};
+typedef struct argument_list_s argument_list_t;
+
+#endif /* AUX_TYPES_H */
diff --git a/src/liboconfig/oconfig.c b/src/liboconfig/oconfig.c
new file mode 100644 (file)
index 0000000..f8d1849
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * oconfig - src/oconfig.c
+ * Copyright (C) 2006,2007  Florian octo Forster <octo at verplant.org>
+ *
+ * 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; only version 2 of the License is applicable.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "oconfig.h"
+
+/* Functions provided by the scanner */
+void yyset_in  (FILE *);
+
+oconfig_item_t *ci_root;
+
+oconfig_item_t *oconfig_parse_fh (FILE *fh)
+{
+  int status;
+  oconfig_item_t *ret;
+
+  yyset_in (fh);
+
+  status = yyparse ();
+  if (status != 0)
+  {
+    fprintf (stderr, "yyparse returned error #%i\n", status);
+    return (NULL);
+  }
+
+  ret = ci_root;
+  ci_root = NULL;
+  yyset_in ((FILE *) 0);
+
+  return (ret);
+} /* oconfig_item_t *oconfig_parse_fh */
+
+oconfig_item_t *oconfig_parse_file (const char *file)
+{
+  FILE *fh;
+  oconfig_item_t *ret;
+
+  fh = fopen (file, "r");
+  if (fh == NULL)
+  {
+    fprintf (stderr, "fopen (%s) failed: %s\n", file, strerror (errno));
+    return (NULL);
+  }
+
+  ret = oconfig_parse_fh (fh);
+  fclose (fh);
+
+  return (ret);
+} /* oconfig_item_t *oconfig_parse_file */
+
+void oconfig_free (oconfig_item_t *ci)
+{
+  int i;
+
+  if (ci->values != NULL)
+    free (ci->values);
+
+  for (i = 0; i < ci->children_num; i++)
+    oconfig_free (ci->children + i);
+}
+
+/*
+ * vim:shiftwidth=2:tabstop=8:softtabstop=2
+ */
diff --git a/src/liboconfig/oconfig.h b/src/liboconfig/oconfig.h
new file mode 100644 (file)
index 0000000..e6e53e2
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef OCONFIG_H
+#define OCONFIG_H 1
+
+#include <stdio.h>
+
+/**
+ * oconfig - src/oconfig.h
+ * Copyright (C) 2006,2007  Florian octo Forster <octo at verplant.org>
+ *
+ * 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; only version 2 of the License is applicable.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+/*
+ * Types
+ */
+#define OCONFIG_TYPE_STRING  0
+#define OCONFIG_TYPE_NUMBER  1
+#define OCONFIG_TYPE_BOOLEAN 2
+
+struct oconfig_value_s
+{
+  union
+  {
+    char  *string;
+    double number;
+    int    boolean;
+  } value;
+  int type;
+};
+typedef struct oconfig_value_s oconfig_value_t;
+
+struct oconfig_item_s;
+typedef struct oconfig_item_s oconfig_item_t;
+struct oconfig_item_s
+{
+  char            *key;
+  oconfig_value_t *values;
+  int              values_num;
+
+  oconfig_item_t  *parent;
+  oconfig_item_t  *children;
+  int              children_num;
+};
+
+/*
+ * Functions
+ */
+oconfig_item_t *oconfig_parse_fh (FILE *fh);
+oconfig_item_t *oconfig_parse_file (const char *file);
+
+void oconfig_free (oconfig_item_t *ci);
+
+/*
+ * vim: shiftwidth=2:tabstop=8:softtabstop=2
+ */
+#endif /* OCONFIG_H */
diff --git a/src/liboconfig/parser.y b/src/liboconfig/parser.y
new file mode 100644 (file)
index 0000000..ea6ed0a
--- /dev/null
@@ -0,0 +1,221 @@
+/**
+ * oconfig - src/parser.y
+ * Copyright (C) 2007  Florian octo Forster <octo at verplant.org>
+ *
+ * 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; only version 2 of the License is applicable.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+%{
+#include <stdlib.h>
+#include <string.h>
+#include "oconfig.h"
+#include "aux_types.h"
+
+static char *unquote (const char *orig);
+static int yyerror (const char *s);
+
+/* Lexer variables */
+extern int yylineno;
+extern char *yytext;
+
+extern oconfig_item_t *ci_root;
+%}
+
+%start entire_file
+
+%union {
+       double  number;
+       int     boolean;
+       char   *string;
+       oconfig_value_t  cv;
+       oconfig_item_t   ci;
+       argument_list_t  al;
+       statement_list_t sl;
+}
+
+%token <number> NUMBER
+%token <boolean> TRUE FALSE
+%token <string> QUOTED_STRING UNQUOTED_STRING
+%token SLASH OPENBRAC CLOSEBRAC EOL
+
+%type <string> string
+%type <string> identifier
+/* arguments */
+%type <cv> argument
+%type <al> argument_list
+/* blocks */
+%type <ci> block_begin
+%type <ci> block
+%type <string> block_end
+/* statements */
+%type <ci> option
+%type <ci> statement
+%type <sl> statement_list
+%type <ci> entire_file
+
+%%
+string:
+       QUOTED_STRING           {$$ = unquote ($1);}
+       | UNQUOTED_STRING       {$$ = strdup ($1);}
+       ;
+
+argument:
+       NUMBER                  {$$.value.number = $1; $$.type = OCONFIG_TYPE_NUMBER;}
+       | TRUE                  {$$.value.boolean = 1; $$.type = OCONFIG_TYPE_BOOLEAN;}
+       | FALSE                 {$$.value.boolean = 0; $$.type = OCONFIG_TYPE_BOOLEAN;}
+       | string                {$$.value.string = $1; $$.type = OCONFIG_TYPE_STRING;}
+       ;
+
+argument_list:
+       argument_list argument
+       {
+        $$ = $1;
+        $$.argument_num++;
+        $$.argument = realloc ($$.argument, $$.argument_num * sizeof (oconfig_value_t));
+        $$.argument[$$.argument_num-1] = $2;
+       }
+       | argument
+       {
+        $$.argument = malloc (sizeof (oconfig_value_t));
+        $$.argument[0] = $1;
+        $$.argument_num = 1;
+       }
+       ;
+
+identifier:
+       UNQUOTED_STRING                 {$$ = strdup ($1);}
+       ;
+
+option:
+       identifier argument_list EOL
+       {
+        memset (&$$, '\0', sizeof ($$));
+        $$.key = $1;
+        $$.values = $2.argument;
+        $$.values_num = $2.argument_num;
+       }
+       ;
+
+block_begin:
+       OPENBRAC identifier argument_list CLOSEBRAC EOL
+       {
+        memset (&$$, '\0', sizeof ($$));
+        $$.key = $2;
+        $$.values = $3.argument;
+        $$.values_num = $3.argument_num;
+       }
+       ;
+
+block_end:
+       OPENBRAC SLASH identifier CLOSEBRAC EOL
+       {
+        $$ = $3;
+       }
+       ;
+
+block:
+       block_begin statement_list block_end
+       {
+        if (strcmp ($1.key, $3) != 0)
+        {
+               printf ("block_begin = %s; block_end = %s;\n", $1.key, $3);
+               yyerror ("Block not closed..\n");
+               exit (1);
+        }
+        free ($3); $3 = NULL;
+        $$ = $1;
+        $$.children = $2.statement;
+        $$.children_num = $2.statement_num;
+       }
+       ;
+
+statement:
+       option          {$$ = $1;}
+       | block         {$$ = $1;}
+       | EOL           {$$.values_num = 0;}
+       ;
+
+statement_list:
+       statement_list statement
+       {
+        $$ = $1;
+        if ($2.values_num > 0)
+        {
+                $$.statement_num++;
+                $$.statement = realloc ($$.statement, $$.statement_num * sizeof (oconfig_item_t));
+                $$.statement[$$.statement_num-1] = $2;
+        }
+       }
+       | statement
+       {
+        if ($1.values_num > 0)
+        {
+                $$.statement = malloc (sizeof (oconfig_item_t));
+                $$.statement[0] = $1;
+                $$.statement_num = 1;
+        }
+        else
+        {
+               $$.statement = NULL;
+               $$.statement_num = 0;
+        }
+       }
+       ;
+
+entire_file:
+       statement_list
+       {
+        ci_root = malloc (sizeof (oconfig_item_t));
+        memset (ci_root, '\0', sizeof (oconfig_item_t));
+        ci_root->children = $1.statement;
+        ci_root->children_num = $1.statement_num;
+       }
+       ;
+
+%%
+static int yyerror (const char *s)
+{
+       fprintf (stderr, "Error in line %i near `%s': %s\n", yylineno, yytext, s);
+       return (-1);
+} /* int yyerror */
+
+static char *unquote (const char *orig)
+{
+       char *ret = strdup (orig);
+       int len;
+       int i;
+
+       if (ret == NULL)
+               return (NULL);
+
+       len = strlen (ret);
+
+       if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"'))
+               return (ret);
+
+       ret++;
+       len -= 2;
+       ret[len] = '\0';
+
+       for (i = 0; i < len; i++)
+       {
+               if (ret[i] == '\\')
+               {
+                       memmove (ret + i, ret + (i + 1), len - i);
+                       len--;
+               }
+       }
+
+       return (ret);
+} /* char *unquote */
diff --git a/src/liboconfig/scanner.l b/src/liboconfig/scanner.l
new file mode 100644 (file)
index 0000000..aa111a2
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * oconfig - src/scanner.l
+ * Copyright (C) 2007  Florian octo Forster <octo at verplant.org>
+ *
+ * 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; only version 2 of the License is applicable.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+%{
+#include <stdlib.h>
+#include "oconfig.h"
+#include "aux_types.h"
+#include "parser.h"
+%}
+WHITE_SPACE [\ \t\b]
+QUOTED_STRING \"([^\\"]+|\\.)*\"
+UNQUOTED_STRING [0-9A-Za-z_]+
+HEX_NUMBER 0[xX][0-9a-fA-F]+
+OCT_NUMBER 0[0-7]+
+DEC_NUMBER [\+\-]?[0-9]+
+FLOAT_NUMBER [\+\-]?[0-9]*\.[0-9]+([eE][\+\-][0-9]+)?
+NUMBER ({FLOAT_NUMBER}|{HEX_NUMBER}|{OCT_NUMBER}|{DEC_NUMBER})
+BOOL_TRUE (true|yes|on)
+BOOL_FALSE (false|no|off)
+COMMENT #.*
+PORT (6(5(5(3[0-5]|[0-2][0-9])|[0-4][0-9][0-9])|[0-4][0-9][0-9][0-9])|[1-5][0-9][0-9][0-9][0-9]|[1-9][0-9]?[0-9]?[0-9]?)
+IP_BYTE (2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])
+IPV4_ADDR {IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}(:{PORT})?
+
+%%
+{WHITE_SPACE}          |
+{COMMENT}              {/* ignore */}
+
+\n                     {return (EOL);}
+"/"                    {return (SLASH);}
+"<"                    {return (OPENBRAC);}
+">"                    {return (CLOSEBRAC);}
+{BOOL_TRUE}            {yylval.boolean = 1; return (TRUE);}
+{BOOL_FALSE}           {yylval.boolean = 0; return (FALSE);}
+
+{IPV4_ADDR}            {yylval.string = yytext; return (UNQUOTED_STRING);}
+
+{NUMBER}               {yylval.number = strtod (yytext, NULL); return (NUMBER);}
+
+{QUOTED_STRING}                {yylval.string = yytext; return (QUOTED_STRING);}
+{UNQUOTED_STRING}      {yylval.string = yytext; return (UNQUOTED_STRING);}
+%%
index 019f952..0876655 100644 (file)
@@ -4,8 +4,7 @@
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 #endif
 #endif /* defined(HAVE_GETLOADAVG) */
 
-static char *load_file = "load.rrd";
-
-static char *ds_def[] =
+static data_source_t dsrc[3] =
 {
-       "DS:shortterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
-       "DS:midterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
-       "DS:longterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
-       NULL
+       {"shortterm", DS_TYPE_GAUGE, 0.0, 100.0},
+       {"midterm",   DS_TYPE_GAUGE, 0.0, 100.0},
+       {"longterm",  DS_TYPE_GAUGE, 0.0, 100.0}
 };
-static int ds_num = 3;
-
-static void load_init (void)
-{
-       return;
-}
 
-static void load_write (char *host, char *inst, char *val)
+static data_set_t ds =
 {
-       rrd_update_file (host, load_file, val, ds_def, ds_num);
-}
+       "load", 3, dsrc
+};
 
 #if LOAD_HAVE_READ
-#define BUFSIZE 256
-static void load_submit (double snum, double mnum, double lnum)
+static void load_submit (gauge_t snum, gauge_t mnum, gauge_t lnum)
 {
-       char buf[BUFSIZE];
+       value_t values[3];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       if (snprintf (buf, BUFSIZE, "%u:%.2f:%.2f:%.2f", (unsigned int) curtime,
-                               snum, mnum, lnum) >= BUFSIZE)
-               return;
+       values[0].gauge = snum;
+       values[1].gauge = mnum;
+       values[2].gauge = lnum;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "load");
 
-       plugin_submit (MODULE_NAME, "-", buf);
+       plugin_dispatch_values ("load", &vl);
 }
-#undef BUFSIZE
 
-static void load_read (void)
+static int load_read (void)
 {
 #if defined(HAVE_GETLOADAVG)
        double load[3];
@@ -91,7 +86,7 @@ static void load_read (void)
 /* #endif HAVE_GETLOADAVG */
 
 #elif defined(KERNEL_LINUX)
-       double snum, mnum, lnum;
+       gauge_t snum, mnum, lnum;
        FILE *loadavg;
        char buffer[16];
 
@@ -127,7 +122,7 @@ static void load_read (void)
 /* #endif KERNEL_LINUX */
 
 #elif defined(HAVE_LIBSTATGRAB)
-       double snum, mnum, lnum;
+       gauge_t snum, mnum, lnum;
        sg_load_stats *ls;
 
        if ((ls = sg_get_load_stats ()) == NULL)
@@ -139,14 +134,17 @@ static void load_read (void)
 
        load_submit (snum, mnum, lnum);
 #endif /* HAVE_LIBSTATGRAB */
+
+       return (0);
 }
-#else
-# define load_read NULL
 #endif /* LOAD_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, load_init, load_read, load_write);
+       plugin_register_data_set (&ds);
+#if LOAD_HAVE_READ
+       plugin_register_read ("load", load_read);
+#endif
 }
 
 #undef MODULE_NAME
index a9bf100..e03f2f9 100644 (file)
 #include "configfile.h"
 #include "utils_debug.h"
 
-#define MODULE_NAME "mbmon"
-
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
+#if HAVE_NETDB_H && HAVE_SYS_SOCKET_H && HAVE_NETINET_IN_H && HAVE_NETINET_TCP_H
+# include <netdb.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# define MBMON_HAVE_READ 1
+#else
+# define MBMON_HAVE_READ 0
+#endif
 
 #define MBMON_DEF_HOST "127.0.0.1"
 #define MBMON_DEF_PORT "411" /* the default for Debian */
 
-/* BUFFER_SIZE
-   Size of the buffer we use to receive from the mbmon daemon. */
-#define BUFFER_SIZE 1024
+static data_source_t data_source_fanspeed[1] =
+{
+       {"value", DS_TYPE_GAUGE, 0, NAN}
+};
 
-static char *filename_temperature = "mbmon/temperature-%s.rrd";
-static char *filename_fanspeed = "mbmon/fanspeed-%s.rrd";
-static char *filename_voltage = "mbmon/voltage-%s.rrd";
+static data_set_t fanspeed_ds =
+{
+       "fanspeed", 1, data_source_fanspeed
+};
 
-/* temperature and fan sensors */
-static char *ds_def[] =
+static data_source_t data_source_temperature[1] =
 {
-       "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
-       NULL
+       {"value", DS_TYPE_GAUGE, -273.15, NAN}
 };
-static int ds_num = 1;
 
-/* voltage sensors */
-static char *voltage_ds_def[] = 
+static data_set_t temperature_ds =
 {
-       "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":U:U",
-       NULL
+       "temperature", 1, data_source_temperature
+};
+
+static data_source_t data_source_voltage[1] =
+{
+       {"voltage", DS_TYPE_GAUGE, NAN, NAN}
 };
-static int voltage_ds_num = 1;
 
-static char *config_keys[] =
+static data_set_t voltage_ds =
+{
+       "voltage", 1, data_source_voltage
+};
+
+static const char *config_keys[] =
 {
        "Host",
        "Port",
@@ -69,6 +78,7 @@ static char *config_keys[] =
 };
 static int config_keys_num = 2;
 
+#if MBMON_HAVE_READ
 static char *mbmon_host = NULL;
 static char *mbmon_port = NULL;
 
@@ -209,7 +219,7 @@ static int mbmon_query_daemon (char *buffer, int buffer_size)
        return (0);
 }
 
-static int mbmon_config (char *key, char *value)
+static int mbmon_config (const char *key, const char *value)
 {
        if (strcasecmp (key, "host") == 0)
        {
@@ -231,60 +241,23 @@ static int mbmon_config (char *key, char *value)
        return (0);
 }
 
-static void mbmon_init (void)
-{
-       return;
-}
-
-static void mbmon_write_temperature (char *host, char *inst, char *val)
-{
-       char filename[BUFFER_SIZE];
-       int status;
-
-       /* construct filename */
-       status = snprintf (filename, BUFFER_SIZE, filename_temperature, inst);
-       if ((status < 1) || (status >= BUFFER_SIZE))
-               return;
-
-       rrd_update_file (host, filename, val, ds_def, ds_num);
-}
-
-static void mbmon_write_fanspeed (char *host, char *inst, char *val)
-{
-       char filename[BUFFER_SIZE];
-       int status;
-
-       /* construct filename */
-       status = snprintf (filename, BUFFER_SIZE, filename_fanspeed, inst);
-       if ((status < 1) || (status >= BUFFER_SIZE))
-               return;
-
-       rrd_update_file (host, filename, val, ds_def, ds_num);
-}
-
-static void mbmon_write_voltage (char *host, char *inst, char *val)
+static void mbmon_submit (const char *type, const char *type_instance,
+               double value)
 {
-       char filename[BUFFER_SIZE];
-       int status;
-
-       /* construct filename */
-       status = snprintf (filename, BUFFER_SIZE, filename_voltage, inst);
-       if ((status < 1) || (status >= BUFFER_SIZE))
-               return;
-
-       rrd_update_file (host, filename, val, voltage_ds_def, voltage_ds_num);
-}
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-static void mbmon_submit (char *type, char *inst, double value)
-{
-       char buf[BUFFER_SIZE];
+       values[0].gauge = value;
 
-       if (snprintf (buf, BUFFER_SIZE, "%u:%.3f", (unsigned int) curtime, value)
-            >= BUFFER_SIZE)
-               return;
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "mbmon");
+       strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
-       plugin_submit (type, inst, buf);
-}
+       plugin_dispatch_values (type, &vl);
+} /* void mbmon_submit */
 
 /* Trim trailing whitespace from a string. */
 static void trim_spaces (char *s)
@@ -295,40 +268,14 @@ static void trim_spaces (char *s)
                s[l] = '\0';
 }
 
-static void mbmon_read (void)
+static int mbmon_read (void)
 {
-       char buf[BUFFER_SIZE];
+       char buf[1024];
        char *s, *t;
 
-       static int wait_time = 1;
-       static int wait_left = 0;
-
-       if (wait_left >= 10)
-       {
-               wait_left -= 10;
-               return;
-       }
-
        /* get data from daemon */
-       if (mbmon_query_daemon (buf, BUFFER_SIZE) < 0)
-       {
-               /* This limit is reached in log2(86400) =~ 17 steps. Since
-                * there is a 2^n seconds wait between each step it will need
-                * roughly one day to reach this limit. -octo */
-               
-               wait_time *= 2;
-               if (wait_time > 86400)
-                       wait_time = 86400;
-
-               wait_left = wait_time;
-
-               return;
-       }
-       else
-       {
-               wait_time = 1;
-               wait_left = 0;
-       }
+       if (mbmon_query_daemon (buf, sizeof (buf)) < 0)
+               return (-1);
 
        s = buf;
        while ((t = strchr (s, ':')) != NULL)
@@ -352,17 +299,17 @@ static void mbmon_read (void)
                if (strncmp (s, "TEMP", 4) == 0)
                {
                        inst = s + 4;
-                       type = "mbmon_temperature";
+                       type = "temperature";
                }
                else if (strncmp (s, "FAN", 3) == 0)
                {
                        inst = s + 3;
-                       type = "mbmon_fanspeed";
+                       type = "fanspeed";
                }
                else if (strncmp (s, "V", 1) == 0)
                {
                        inst = s + 1;
-                       type = "mbmon_voltage";
+                       type = "voltage";
                }
                else
                {
@@ -376,17 +323,21 @@ static void mbmon_read (void)
 
                s = nextc + 1;
        }
+
+       return (0);
 } /* void mbmon_read */
+#endif /* MBMON_HAVE_READ */
 
 /* module_register
    Register collectd plugin. */
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, mbmon_init, mbmon_read, NULL);
-       plugin_register ("mbmon_temperature", NULL, NULL, mbmon_write_temperature);
-       plugin_register ("mbmon_fanspeed", NULL, NULL, mbmon_write_fanspeed);
-       plugin_register ("mbmon_voltage", NULL, NULL, mbmon_write_voltage);
-       cf_register (MODULE_NAME, mbmon_config, config_keys, config_keys_num);
+       plugin_register_data_set (&fanspeed_ds);
+       plugin_register_data_set (&temperature_ds);
+       plugin_register_data_set (&voltage_ds);
+
+#if MBMON_HAVE_READ
+       plugin_register_config ("mbmon", mbmon_config, config_keys, config_keys_num);
+       plugin_register_read ("mbmon", mbmon_read);
+#endif /* MBMON_HAVE_READ */
 }
-
-#undef MODULE_NAME
index b8b7229..38a6dc2 100644 (file)
@@ -1,11 +1,10 @@
 /**
  * collectd - src/memory.c
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 # define MEMORY_HAVE_READ 0
 #endif
 
-#define MODULE_NAME "memory"
-
-static char *memory_file = "memory.rrd";
+/* 2^48 = 281474976710656 */
+static data_source_t dsrc[4] =
+{
+       {"used",    DS_TYPE_GAUGE, 0, 281474976710656.0},
+       {"free",    DS_TYPE_GAUGE, 0, 281474976710656.0},
+       {"buffers", DS_TYPE_GAUGE, 0, 281474976710656.0},
+       {"cached",  DS_TYPE_GAUGE, 0, 281474976710656.0}
+};
 
-/* 9223372036854775807 == LLONG_MAX */
-static char *ds_def[] =
+static data_set_t ds =
 {
-       "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:buffers:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       NULL
+       "memory", 4, dsrc
 };
-static int ds_num = 4;
 
 /* vm_statistics_data_t */
 #if defined(HOST_VM_INFO)
@@ -85,7 +83,8 @@ static int pagesize;
 static kstat_t *ksp;
 #endif /* HAVE_LIBKSTAT */
 
-static void memory_init (void)
+#if MEMORY_HAVE_READ
+static int memory_init (void)
 {
 #if defined(HOST_VM_INFO)
        port_host = mach_host_self ();
@@ -107,31 +106,30 @@ static void memory_init (void)
                ksp = NULL;
 #endif /* HAVE_LIBKSTAT */
 
-       return;
-}
-
-static void memory_write (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, memory_file, val, ds_def, ds_num);
-}
+       return (0);
+} /* int memory_init */
 
-#if MEMORY_HAVE_READ
-#define BUFSIZE 512
 static void memory_submit (long long mem_used, long long mem_buffered,
                long long mem_cached, long long mem_free)
 {
-       char buf[BUFSIZE];
+       value_t values[4];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = mem_used;
+       values[1].gauge = mem_free;
+       values[2].gauge = mem_buffered;
+       values[3].gauge = mem_cached;
 
-       if (snprintf (buf, BUFSIZE, "%u:%lli:%lli:%lli:%lli",
-                               (unsigned int) curtime, mem_used, mem_free,
-                               mem_buffered, mem_cached) >= BUFSIZE)
-               return;
+       vl.values = values;
+       vl.values_len = 4;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "memory");
 
-       plugin_submit (MODULE_NAME, "-", buf);
+       plugin_dispatch_values ("memory", &vl);
 }
-#undef BUFSIZE
 
-static void memory_read (void)
+static int memory_read (void)
 {
 #if defined(HOST_VM_INFO)
        kern_return_t status;
@@ -144,7 +142,7 @@ static void memory_read (void)
        long long free;
 
        if (!port_host || !pagesize)
-               return;
+               return (-1);
 
        vm_data_len = sizeof (vm_data) / sizeof (natural_t);
        if ((status = host_statistics (port_host, HOST_VM_INFO,
@@ -152,7 +150,7 @@ static void memory_read (void)
                                        &vm_data_len)) != KERN_SUCCESS)
        {
                syslog (LOG_ERR, "memory-plugin: host_statistics failed and returned the value %i", (int) status);
-               return;
+               return (-1);
        }
 
        /*
@@ -219,7 +217,7 @@ static void memory_read (void)
                {
                        syslog (LOG_ERR, "memory plugin: sysctlbyname (%s): %s",
                                        sysctl_keys[i], strerror (errno));
-                       return;
+                       return (-1);
                }
                DBG ("%26s: %6i", sysctl_keys[i], sysctl_vals[i]);
        } /* for i */
@@ -249,7 +247,7 @@ static void memory_read (void)
        if ((fh = fopen ("/proc/meminfo", "r")) == NULL)
        {
                syslog (LOG_WARNING, "memory: fopen: %s", strerror (errno));
-               return;
+               return (-1);
        }
 
        while (fgets (buffer, 1024, fh) != NULL)
@@ -291,16 +289,16 @@ static void memory_read (void)
        long long mem_lock;
 
        if (ksp == NULL)
-               return;
+               return (-1);
 
        mem_used = get_kstat_value (ksp, "pagestotal");
        mem_free = get_kstat_value (ksp, "pagesfree");
        mem_lock = get_kstat_value (ksp, "pageslocked");
 
        if ((mem_used < 0LL) || (mem_free < 0LL) || (mem_lock < 0LL))
-               return;
+               return (-1);
        if (mem_used < (mem_free + mem_lock))
-               return;
+               return (-1);
 
        mem_used -= mem_free + mem_lock;
        mem_used *= pagesize; /* If this overflows you have some serious */
@@ -316,14 +314,17 @@ static void memory_read (void)
        if ((ios = sg_get_mem_stats ()) != NULL)
                memory_submit (ios->used, 0LL, ios->cache, ios->free);
 #endif /* HAVE_LIBSTATGRAB */
+
+       return (0);
 }
-#else
-# define memory_read NULL
 #endif /* MEMORY_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, memory_init, memory_read, memory_write);
-}
+       plugin_register_data_set (&ds);
 
-#undef MODULE_NAME
+#if MEMORY_HAVE_READ
+       plugin_register_init ("memory", memory_init);
+       plugin_register_read ("memory", memory_read);
+#endif /* MEMORY_HAVE_READ */
+}
index 46438bf..8cb18c8 100644 (file)
  *   Peter Holik <peter at holik.at>
  *
  * Used multimeter: Metex M-4650CR
- *
  **/
 
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <math.h>
 #include "collectd.h"
 #include "common.h"
 #include "plugin.h"
 
-#define MODULE_NAME "multimeter"
-
-static char *multimeter_file = "multimeter.rrd";
+#if HAVE_TERMIOS_H && HAVE_SYS_IOCTL_H && HAVE_MATH_H
+# include <termios.h>
+# include <sys/ioctl.h>
+# include <math.h>
+# define MULTIMETER_HAVE_READ 1
+#else
+# define MULTIMETER_HAVE_READ 0
+# error "multimeter cannot read!"
+#endif
+
+static data_source_t data_source[1] =
+{
+       {"value", DS_TYPE_GAUGE, NAN, NAN}
+};
 
-static char *ds_def[] =
+static data_set_t data_set =
 {
-       "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
-       NULL
+       "multimeter", 1, data_source
 };
-static int ds_num = 1;
 
+#if MULTIMETER_HAVE_READ
 static int fd = -1;
 
 static int multimeter_timeval_sub (struct timeval *tv1, struct timeval *tv2,
@@ -75,7 +81,7 @@ static int multimeter_read_value(double *value)
 
                if (gettimeofday (&time_end, NULL) < 0)
                {
-                       syslog (LOG_ERR, MODULE_NAME": gettimeofday failed: %s",
+                       syslog (LOG_ERR, "multimeter plugin: gettimeofday failed: %s",
                                 strerror (errno));
                        return (-1);
                }
@@ -97,8 +103,9 @@ static int multimeter_read_value(double *value)
 
                        if (gettimeofday (&time_now, NULL) < 0)
                        {
-                               syslog (LOG_ERR, MODULE_NAME": gettimeofday failed: %s",
-                                        strerror (errno));
+                               syslog (LOG_ERR, "multimeter plugin: "
+                                               "gettimeofday failed: %s",
+                                               strerror (errno));
                                return (-1);
                        }
                        if (multimeter_timeval_sub (&time_end, &time_now, &timeout) == -1)
@@ -150,17 +157,18 @@ static int multimeter_read_value(double *value)
                        }
                        else /* status == -1 */
                        {
-                               syslog (LOG_ERR, MODULE_NAME": select failed: %s",
-                                        strerror (errno));
+                               syslog (LOG_ERR, "multimeter plugin: "
+                                               "select failed: %s",
+                                               strerror (errno));
                                break;
                        }
                }
        } while (--retry);
 
        return (-2);  /* no value received */
-}
+} /* int multimeter_read_value */
 
-static void multimeter_init (void)
+static int multimeter_init (void)
 {
        int i;
        char device[] = "/dev/ttyS ";
@@ -186,49 +194,74 @@ static void multimeter_init (void)
                        tcsetattr(fd, TCSANOW, &tios);
                        ioctl(fd, TIOCMBIC, &rts);
                        
-                       if (multimeter_read_value(&value) < -1)
+                       if (multimeter_read_value (&value) < -1)
                        {
-                               close(fd);
+                               close (fd);
                                fd = -1;
                        }
                        else
                        {
-                               syslog (LOG_INFO, MODULE_NAME" found (%s)", device);
-                               return;
+                               syslog (LOG_INFO, "multimeter plugin: Device "
+                                               "found at %s", device);
+                               return (0);
                        }
                }
        }
-       syslog (LOG_ERR, MODULE_NAME" not found");
+
+       syslog (LOG_ERR, "multimeter plugin: No device found");
+       return (-1);
 }
 #undef LINE_LENGTH
 
-static void multimeter_write (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, multimeter_file, val, ds_def, ds_num);
-}
-#define BUFSIZE 128
-static void multimeter_submit (double *value)
+static void multimeter_submit (double value)
 {
-       char buf[BUFSIZE];
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       if (snprintf (buf, BUFSIZE, "%u:%f", (unsigned int) curtime, *value) >= BUFSIZE)
-               return;
+       values[0].gauge = value;
 
-       plugin_submit (MODULE_NAME, "-", buf);
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "multimeter");
+
+       plugin_dispatch_values ("multimeter", &vl);
 }
-#undef BUFSIZE
 
-static void multimeter_read (void)
+static int multimeter_read (void)
 {
        double value;
 
-       if (fd > -1 && !(multimeter_read_value(&value)))
-               multimeter_submit (&value);
+       if (fd < 0)
+               return (-1);
+
+       if (multimeter_read_value (&value) != 0)
+               return (-1);
+
+       multimeter_submit (value);
+       return (0);
+} /* int multimeter_read */
+
+static int multimeter_shutdown (void)
+{
+       if (fd >= 0)
+       {
+               close (fd);
+               fd = -1;
+       }
+
+       return (0);
 }
+#endif /* MULTIMETER_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, multimeter_init, multimeter_read, multimeter_write);
-}
+       plugin_register_data_set (&data_set);
 
-#undef MODULE_NAME
+#if MULTIMETER_HAVE_READ
+       plugin_register_init ("multimeter", multimeter_init);
+       plugin_register_read ("multimeter", multimeter_read);
+       plugin_register_shutdown ("multimeter", multimeter_shutdown);
+#endif /* MULTIMETER_HAVE_READ */
+}
index caebdf3..a2604e4 100644 (file)
@@ -1,11 +1,10 @@
 /**
  * collectd - src/mysql.c
- * Copyright (C) 2006  Florian octo Forster
+ * Copyright (C) 2006,2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 #include <mysql/mysql.h>
 #endif
 
-#define MODULE_NAME "mysql"
-
 #if COLLECT_LIBMYSQL
 # define MYSQL_HAVE_READ 1
 #else
 # define MYSQL_HAVE_READ 0
 #endif
 
-#define BUFSIZE 512
+/* TODO: Understand `Select_*' and possibly do that stuff as well.. */
 
-static char *host = "localhost";
-static char *user;
-static char *pass;
-static char *db = NULL;
+static data_source_t data_source_counter[1] =
+{
+       {"value", DS_TYPE_COUNTER, 0, NAN}
+};
 
-/* TODO
- * understand `Select_*' and possibly do that stuff as well..
- */
+static data_set_t ds_commands =
+{
+       "mysql_commands", 1, data_source_counter
+};
 
-static char *commands_file = "mysql/mysql_commands-%s.rrd";
-static char *handler_file  = "mysql/mysql_handler-%s.rrd";
-static char *qcache_file   = "mysql/mysql_qcache.rrd";
-static char *threads_file  = "mysql/mysql_threads.rrd";
-static char *traffic_file  = "traffic-mysql.rrd";
+static data_set_t ds_handler =
+{
+       "mysql_handler", 1, data_source_counter
+};
 
-static char *commands_ds_def[] =
+static data_source_t data_source_qcache[5] =
 {
-       "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       {"hits",             DS_TYPE_COUNTER, 0, NAN},
+       {"inserts",          DS_TYPE_COUNTER, 0, NAN},
+       {"not_cached",       DS_TYPE_COUNTER, 0, NAN},
+       {"lowmem_prunes",    DS_TYPE_COUNTER, 0, NAN},
+       {"queries_in_cache", DS_TYPE_GAUGE,   0, NAN}
 };
-static int commands_ds_num = 1;
 
-static char *handler_ds_def[] =
+static data_set_t ds_qcache =
 {
-       "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       "mysql_qcache", 5, data_source_qcache
 };
-static int handler_ds_num = 1;
 
-static char *qcache_ds_def[] =
+static data_source_t data_source_threads[4] =
 {
-       "DS:hits:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:inserts:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:not_cached:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:lowmem_prunes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:queries_in_cache:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       {"running",   DS_TYPE_GAUGE,   0, NAN},
+       {"connected", DS_TYPE_GAUGE,   0, NAN},
+       {"cached",    DS_TYPE_GAUGE,   0, NAN},
+       {"created",   DS_TYPE_COUNTER, 0, NAN}
 };
-static int qcache_ds_num = 5;
 
-static char *threads_ds_def[] =
+static data_set_t ds_threads =
 {
-       "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       "DS:connected:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       "DS:created:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       "mysql_threads", 4, data_source_threads
 };
-static int threads_ds_num = 4;
 
-static char *traffic_ds_def[] =
+static data_source_t data_source_octets[2] =
 {
-       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+       {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
 };
-static int traffic_ds_num = 2;
 
-static char *config_keys[] =
+static data_set_t ds_octets =
+{
+       "mysql_octets", 2, data_source_octets
+};
+
+#if MYSQL_HAVE_READ
+static const char *config_keys[] =
 {
        "Host",
        "User",
@@ -107,7 +100,11 @@ static char *config_keys[] =
 };
 static int config_keys_num = 4;
 
-#if MYSQL_HAVE_READ
+static char *host = "localhost";
+static char *user;
+static char *pass;
+static char *db = NULL;
+
 static MYSQL *getconnection (void)
 {
        static MYSQL *con;
@@ -167,14 +164,8 @@ static MYSQL *getconnection (void)
                return (con);
        }
 } /* static MYSQL *getconnection (void) */
-#endif /* MYSQL_HAVE_READ */
-
-static void init (void)
-{
-       return;
-}
 
-static int config (char *key, char *value)
+static int config (const char *key, const char *value)
 {
        if (strcasecmp (key, "host") == 0)
                return ((host = strdup (value)) == NULL ? 1 : 0);
@@ -188,160 +179,84 @@ static int config (char *key, char *value)
                return (-1);
 }
 
-static void commands_write (char *host, char *inst, char *val)
-{
-       char buf[BUFSIZE];
-
-       if (snprintf (buf, BUFSIZE, commands_file, inst) >= BUFSIZE)
-               return;
-
-       rrd_update_file (host, buf, val, commands_ds_def, commands_ds_num);
-}
-
-static void handler_write (char *host, char *inst, char *val)
-{
-       char buf[BUFSIZE];
-
-       if (snprintf (buf, BUFSIZE, handler_file, inst) >= BUFSIZE)
-               return;
-
-       rrd_update_file (host, buf, val, handler_ds_def, handler_ds_num);
-}
-
-static void qcache_write (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, qcache_file, val,
-                       qcache_ds_def, qcache_ds_num);
-}
-
-static void threads_write (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, threads_file, val,
-                       threads_ds_def, threads_ds_num);
-}
-
-static void traffic_write (char *host, char *inst, char *val)
+static void counter_submit (const char *type, const char *type_instance,
+               counter_t value)
 {
-       rrd_update_file (host, traffic_file, val,
-                       traffic_ds_def, traffic_ds_num);
-}
-
-#if MYSQL_HAVE_READ
-static void commands_submit (char *inst, unsigned long long value)
-{
-       char buf[BUFSIZE];
-       int  status;
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       status = snprintf (buf, BUFSIZE, "%u:%llu", (unsigned int) curtime, value);
+       values[0].counter = value;
 
-       if (status < 0)
-       {
-               syslog (LOG_ERR, "snprintf failed");
-               return;
-       }
-       else if (status >= BUFSIZE)
-       {
-               syslog (LOG_WARNING, "snprintf was truncated");
-               return;
-       }
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "mysql");
+       strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
-       plugin_submit ("mysql_commands", inst, buf);
-}
+       plugin_dispatch_values (type, &vl);
+} /* void counter_submit */
 
-static void handler_submit (char *inst, unsigned long long value)
+static void qcache_submit (counter_t hits, counter_t inserts,
+               counter_t not_cached, counter_t lowmem_prunes,
+               gauge_t queries_in_cache)
 {
-       char buf[BUFSIZE];
-       int  status;
-
-       status = snprintf (buf, BUFSIZE, "%u:%llu", (unsigned int) curtime, value);
-
-       if (status < 0)
-       {
-               syslog (LOG_ERR, "snprintf failed");
-               return;
-       }
-       else if (status >= BUFSIZE)
-       {
-               syslog (LOG_WARNING, "snprintf was truncated");
-               return;
-       }
-
-       plugin_submit ("mysql_handler", inst, buf);
-}
-
-static void qcache_submit (unsigned long long hits, unsigned long long inserts,
-               unsigned long long not_cached, unsigned long long lowmem_prunes,
-               int queries_in_cache)
-{
-       char buf[BUFSIZE];
-       int  status;
-
-       status = snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%i",
-                       (unsigned int) curtime, hits, inserts, not_cached,
-                       lowmem_prunes, queries_in_cache);
-
-       if (status < 0)
-       {
-               syslog (LOG_ERR, "snprintf failed");
-               return;
-       }
-       else if (status >= BUFSIZE)
-       {
-               syslog (LOG_WARNING, "snprintf was truncated");
-               return;
-       }
-
-       plugin_submit ("mysql_qcache", "-", buf);
-}
-
-static void threads_submit (int running, int connected, int cached,
-               unsigned long long created)
+       value_t values[5];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].counter = hits;
+       values[1].counter = inserts;
+       values[2].counter = not_cached;
+       values[3].counter = lowmem_prunes;
+       values[4].gauge   = queries_in_cache;
+
+       vl.values = values;
+       vl.values_len = 5;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "mysql");
+
+       plugin_dispatch_values ("mysql_qcache", &vl);
+} /* void qcache_submit */
+
+static void threads_submit (gauge_t running, gauge_t connected, gauge_t cached,
+               counter_t created)
 {
-       char buf[BUFSIZE];
-       int  status;
+       value_t values[4];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       status = snprintf (buf, BUFSIZE, "%u:%i:%i:%i:%llu",
-                       (unsigned int) curtime,
-                       running, connected, cached, created);
+       values[0].gauge   = running;
+       values[1].gauge   = connected;
+       values[2].gauge   = cached;
+       values[3].counter = created;
 
-       if (status < 0)
-       {
-               syslog (LOG_ERR, "snprintf failed");
-               return;
-       }
-       else if (status >= BUFSIZE)
-       {
-               syslog (LOG_WARNING, "snprintf was truncated");
-               return;
-       }
+       vl.values = values;
+       vl.values_len = 4;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "mysql");
 
-       plugin_submit ("mysql_threads", "-", buf);
-}
+       plugin_dispatch_values ("mysql_threads", &vl);
+} /* void threads_submit */
 
-static void traffic_submit (unsigned long long incoming,
-               unsigned long long outgoing)
+static void traffic_submit (counter_t rx, counter_t tx)
 {
-       char buf[BUFSIZE];
-       int  status;
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       status = snprintf (buf, BUFSIZE, "%u:%llu:%llu", (unsigned int) curtime,
-                       incoming, outgoing);
+       values[0].counter = rx;
+       values[1].counter = tx;
 
-       if (status < 0)
-       {
-               syslog (LOG_ERR, "snprintf failed");
-               return;
-       }
-       else if (status >= BUFSIZE)
-       {
-               syslog (LOG_WARNING, "snprintf was truncated");
-               return;
-       }
+       vl.values = values;
+       vl.values_len = 2;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "mysql");
 
-       plugin_submit ("mysql_traffic", "-", buf);
-}
+       plugin_dispatch_values ("mysql_octets", &vl);
+} /* void traffic_submit */
 
-static void mysql_read (void)
+static int mysql_read (void)
 {
        MYSQL     *con;
        MYSQL_RES *res;
@@ -366,7 +281,7 @@ static void mysql_read (void)
 
        /* An error message will have been printed in this case */
        if ((con = getconnection ()) == NULL)
-               return;
+               return (-1);
 
        query = "SHOW STATUS";
        if (mysql_get_server_version (con) >= 50002)
@@ -378,14 +293,14 @@ static void mysql_read (void)
        {
                syslog (LOG_ERR, "mysql_real_query failed: %s\n",
                                mysql_error (con));
-               return;
+               return (-1);
        }
 
        if ((res = mysql_store_result (con)) == NULL)
        {
                syslog (LOG_ERR, "mysql_store_result failed: %s\n",
                                mysql_error (con));
-               return;
+               return (-1);
        }
 
        field_num = mysql_num_fields (res);
@@ -404,14 +319,14 @@ static void mysql_read (void)
 
                        /* Ignore `prepared statements' */
                        if (strncmp (key, "Com_stmt_", 9) != 0)
-                               commands_submit (key + 4, val);
+                               counter_submit ("mysql_commands", key + 4, val);
                }
                else if (strncmp (key, "Handler_", 8) == 0)
                {
                        if (val == 0ULL)
                                continue;
 
-                       handler_submit (key + 8, val);
+                       counter_submit ("mysql_handler", key + 8, val);
                }
                else if (strncmp (key, "Qcache_", 7) == 0)
                {
@@ -462,22 +377,20 @@ static void mysql_read (void)
 
        /* mysql_close (con); */
 
-       return;
-}
-#else
-# define mysql_read NULL
+       return (0);
+} /* int mysql_read */
 #endif /* MYSQL_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, init, mysql_read, NULL);
-       plugin_register ("mysql_commands", NULL, NULL, commands_write);
-       plugin_register ("mysql_handler",  NULL, NULL, handler_write);
-       plugin_register ("mysql_qcache",   NULL, NULL, qcache_write);
-       plugin_register ("mysql_threads",  NULL, NULL, threads_write);
-       plugin_register ("mysql_traffic",  NULL, NULL, traffic_write);
-       cf_register (MODULE_NAME, config, config_keys, config_keys_num);
-}
+       plugin_register_data_set (&ds_commands);
+       plugin_register_data_set (&ds_handler);
+       plugin_register_data_set (&ds_qcache);
+       plugin_register_data_set (&ds_threads);
+       plugin_register_data_set (&ds_octets);
 
-#undef BUFSIZE
-#undef MODULE_NAME
+#if MYSQL_HAVE_READ
+       plugin_register_config ("mysql", config, config_keys, config_keys_num);
+       plugin_register_read ("mysql", mysql_read);
+#endif /* MYSQL_HAVE_READ */
+} /* void module_register */
index e9ba84b..cf2a017 100644 (file)
@@ -1,11 +1,10 @@
 /**
  * collectd - src/network.c
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  *   Florian octo Forster <octo at verplant.org>
  **/
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <syslog.h>
-#include <errno.h>
-
-#include "network.h"
+#include "collectd.h"
+#include "plugin.h"
 #include "common.h"
 #include "configfile.h"
 #include "utils_debug.h"
 
+#include "network.h"
+
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#if HAVE_POLL_H
+# include <poll.h>
+#endif
+
 /* 1500 - 40 - 8  =  Ethernet packet - IPv6 header - UDP header */
 /* #define BUFF_SIZE 1452 */
 
 # endif
 #endif /* !IP_ADD_MEMBERSHIP */
 
-#define BUFF_SIZE 4096
-
-extern int operating_mode;
+#define BUFF_SIZE 1024
 
+/*
+ * Private data types
+ */
 typedef struct sockent
 {
        int                      fd;
-       int                      mode;
        struct sockaddr_storage *addr;
        socklen_t                addrlen;
        struct sockent          *next;
 } sockent_t;
 
-static sockent_t *socklist_head = NULL;
+/*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------+-----------------------+-------------------------------+
+ * ! Ver.  !                       ! Length                        !
+ * +-------+-----------------------+-------------------------------+
+ */
+struct part_header_s
+{
+       uint16_t type;
+       uint16_t length;
+};
+typedef struct part_header_s part_header_t;
+
+/*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type                          ! Length                        !
+ * +-------------------------------+-------------------------------+
+ * : (Length - 4) Bytes                                            :
+ * +---------------------------------------------------------------+
+ */
+struct part_string_s
+{
+       part_header_t *head;
+       char *value;
+};
+typedef struct part_string_s part_string_t;
+
+/*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type                          ! Length                        !
+ * +-------------------------------+-------------------------------+
+ * : (Length - 4 == 2 || 4 || 8) Bytes                             :
+ * +---------------------------------------------------------------+
+ */
+struct part_number_s
+{
+       part_header_t *head;
+       uint64_t *value;
+};
+typedef struct part_number_s part_number_t;
+
+/*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type                          ! Length                        !
+ * +-------------------------------+---------------+---------------+
+ * ! Num of values                 ! Type0         ! Type1         !
+ * +-------------------------------+---------------+---------------+
+ * ! Value0                                                        !
+ * !                                                               !
+ * +---------------------------------------------------------------+
+ * ! Value1                                                        !
+ * !                                                               !
+ * +---------------------------------------------------------------+
+ */
+struct part_values_s
+{
+       part_header_t *head;
+       uint16_t *num_values;
+       uint8_t  *values_types;
+       value_t  *values;
+};
+typedef struct part_values_s part_values_t;
+
+/*
+ * Private variables
+ */
+static const char *config_keys[] =
+{
+       "Listen",
+       "Server",
+       "TimeToLive",
+       NULL
+};
+static int config_keys_num = 3;
+
+static int network_config_ttl = 0;
+
+static sockent_t *sending_sockets = NULL;
+
+static struct pollfd *listen_sockets = NULL;
+static int listen_sockets_num = 0;
+static pthread_t listen_thread = 0;
+static int listen_loop = 0;
+
+static char         send_buffer[BUFF_SIZE];
+static char        *send_buffer_ptr;
+static int          send_buffer_fill;
+static value_list_t send_buffer_vl = VALUE_LIST_INIT;
+static char         send_buffer_type[DATA_MAX_NAME_LEN];
+
+/*
+ * Private functions
+ */
+static int write_part_values (char **ret_buffer, int *ret_buffer_len,
+               const data_set_t *ds, const value_list_t *vl)
+{
+       part_values_t pv;
+       int i;
+
+       i = 6 + (9 * vl->values_len);
+       if (*ret_buffer_len < i)
+               return (-1);
+       *ret_buffer_len -= i;
+
+       pv.head = (part_header_t *) *ret_buffer;
+       pv.num_values = (uint16_t *) (pv.head + 1);
+       pv.values_types = (uint8_t *) (pv.num_values + 1);
+       pv.values = (value_t *) (pv.values_types + vl->values_len);
+       *ret_buffer = (void *) (pv.values + vl->values_len);
+
+       pv.head->type = htons (TYPE_VALUES);
+       pv.head->length = htons (6 + (9 * vl->values_len));
+       *pv.num_values = htons ((uint16_t) vl->values_len);
+       
+       for (i = 0; i < vl->values_len; i++)
+       {
+               if (ds->ds[i].type == DS_TYPE_COUNTER)
+               {
+                       pv.values_types[i] = DS_TYPE_COUNTER;
+                       pv.values[i].counter = htonll (vl->values[i].counter);
+               }
+               else
+               {
+                       pv.values_types[i] = DS_TYPE_GAUGE;
+                       pv.values[i].gauge = vl->values[i].gauge;
+               }
+       } /* for (values) */
 
-static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
+       return (0);
+} /* int write_part_values */
+
+static int write_part_number (char **ret_buffer, int *ret_buffer_len,
+               int type, uint64_t value)
 {
-       char *ttl_str;
-       int   ttl_int;
+       part_number_t pn;
 
-       ttl_str = cf_get_option ("TimeToLive", NULL);
-       if (ttl_str == NULL)
+       if (*ret_buffer_len < 12)
                return (-1);
 
-       ttl_int = atoi (ttl_str);
-       if ((ttl_int < 1) || (ttl_int > 255))
+       pn.head = (part_header_t *) *ret_buffer;
+       pn.value = (uint64_t *) (pn.head + 1);
+
+       pn.head->type = htons (type);
+       pn.head->length = htons (12);
+       *pn.value = htonll (value);
+
+       *ret_buffer = (char *) (pn.value + 1);
+       *ret_buffer_len -= 12;
+
+       return (0);
+} /* int write_part_number */
+
+static int write_part_string (char **ret_buffer, int *ret_buffer_len,
+               int type, const char *str, int str_len)
+{
+       part_string_t ps;
+       int len;
+
+       len = 4 + str_len + 1;
+       if (*ret_buffer_len < len)
+               return (-1);
+       *ret_buffer_len -= len;
+
+       ps.head = (part_header_t *) *ret_buffer;
+       ps.value = (char *) (ps.head + 1);
+
+       ps.head->type = htons ((uint16_t) type);
+       ps.head->length = htons ((uint16_t) str_len + 5);
+       if (str_len > 0)
+               memcpy (ps.value, str, str_len);
+       ps.value[str_len] = '\0';
+       *ret_buffer = (void *) (ps.value + (str_len + 1));
+
+       return (0);
+} /* int write_part_string */
+
+static int parse_part_values (void **ret_buffer, int *ret_buffer_len,
+               value_t **ret_values, int *ret_num_values)
+{
+       char *buffer = *ret_buffer;
+       int   buffer_len = *ret_buffer_len;
+       part_values_t pv;
+       int   i;
+
+       uint16_t h_length;
+       uint16_t h_type;
+       uint16_t h_num;
+
+       if (buffer_len < (15))
        {
-               syslog (LOG_WARNING, "A TTL value of %i is invalid.", ttl_int);
+               DBG ("packet is too short: buffer_len = %i", buffer_len);
                return (-1);
        }
 
-       DBG ("ttl = %i", ttl_int);
+       pv.head = (part_header_t *) buffer;
+       h_length = ntohs (pv.head->length);
+       h_type = ntohs (pv.head->type);
+
+       assert (h_type == TYPE_VALUES);
+
+       pv.num_values = (uint16_t *) (pv.head + 1);
+       h_num = ntohs (*pv.num_values);
+
+       if (h_num != ((h_length - 6) / 9))
+       {
+               DBG ("`length' and `num of values' don't match");
+               return (-1);
+       }
+
+       pv.values_types = (uint8_t *) (pv.num_values + 1);
+       pv.values = (value_t *) (pv.values_types + h_num);
+
+       for (i = 0; i < h_num; i++)
+               if (pv.values_types[i] == DS_TYPE_COUNTER)
+                       pv.values[i].counter = ntohll (pv.values[i].counter);
+
+       *ret_buffer     = (void *) (pv.values + h_num);
+       *ret_buffer_len = buffer_len - h_length;
+       *ret_num_values = h_num;
+       *ret_values     = pv.values;
+
+       return (0);
+} /* int parse_part_values */
+
+static int parse_part_number (void **ret_buffer, int *ret_buffer_len,
+               uint64_t *value)
+{
+       part_number_t pn;
+       uint16_t len;
+
+       pn.head = (part_header_t *) *ret_buffer;
+       pn.value = (uint64_t *) (pn.head + 1);
+
+       len = ntohs (pn.head->length);
+       if (len != 12)
+               return (-1);
+       if (len > *ret_buffer_len)
+               return (-1);
+       *value = ntohll (*pn.value);
+
+       *ret_buffer = (void *) (pn.value + 1);
+       *ret_buffer_len -= len;
+
+       return (0);
+} /* int parse_part_number */
+
+static int parse_part_string (void **ret_buffer, int *ret_buffer_len,
+               char *output, int output_len)
+{
+       char *buffer = *ret_buffer;
+       int   buffer_len = *ret_buffer_len;
+       part_string_t ps;
+
+       uint16_t h_length;
+       uint16_t h_type;
+
+       DBG ("ret_buffer = %p; ret_buffer_len = %i; output = %p; output_len = %i;",
+                       *ret_buffer, *ret_buffer_len,
+                       (void *) output, output_len);
+
+       ps.head = (part_header_t *) buffer;
+
+       h_length = ntohs (ps.head->length);
+       h_type = ntohs (ps.head->type);
+
+       DBG ("length = %hu; type = %hu;", h_length, h_type);
+
+       if (buffer_len < h_length)
+       {
+               DBG ("packet is too short");
+               return (-1);
+       }
+       assert ((h_type == TYPE_HOST)
+                       || (h_type == TYPE_PLUGIN)
+                       || (h_type == TYPE_PLUGIN_INSTANCE)
+                       || (h_type == TYPE_TYPE)
+                       || (h_type == TYPE_TYPE_INSTANCE));
+
+       ps.value = buffer + 4;
+       if (ps.value[h_length - 5] != '\0')
+       {
+               DBG ("String does not end with a nullbyte");
+               return (-1);
+       }
+
+       if (output_len < (h_length - 4))
+       {
+               DBG ("output buffer is too small");
+               return (-1);
+       }
+       strcpy (output, ps.value);
+
+       DBG ("output = %s", output);
+
+       *ret_buffer = (void *) (buffer + h_length);
+       *ret_buffer_len = buffer_len - h_length;
+
+       return (0);
+} /* int parse_part_string */
+
+static int parse_packet (void *buffer, int buffer_len)
+{
+       part_header_t *header;
+       int status;
+
+       value_list_t vl = VALUE_LIST_INIT;
+       char type[DATA_MAX_NAME_LEN];
+
+       DBG ("buffer = %p; buffer_len = %i;", buffer, buffer_len);
+
+       memset (&vl, '\0', sizeof (vl));
+       memset (&type, '\0', sizeof (type));
+       status = 0;
+
+       while ((status == 0) && (buffer_len > sizeof (part_header_t)))
+       {
+               header = (part_header_t *) buffer;
+
+               if (ntohs (header->length) > buffer_len)
+                       break;
+
+               if (header->type == htons (TYPE_VALUES))
+               {
+                       status = parse_part_values (&buffer, &buffer_len,
+                                       &vl.values, &vl.values_len);
+
+                       if (status != 0)
+                       {
+                               DBG ("parse_part_values failed.");
+                               break;
+                       }
+
+                       if ((vl.time > 0)
+                                       && (strlen (vl.host) > 0)
+                                       && (strlen (vl.plugin) > 0)
+                                       && (strlen (type) > 0))
+                       {
+                               DBG ("dispatching values");
+                               plugin_dispatch_values (type, &vl);
+                       }
+                       else
+                       {
+                               DBG ("NOT dispatching values");
+                       }
+               }
+               else if (header->type == ntohs (TYPE_TIME))
+               {
+                       uint64_t tmp = 0;
+                       status = parse_part_number (&buffer, &buffer_len, &tmp);
+                       if (status == 0)
+                               vl.time = (time_t) tmp;
+               }
+               else if (header->type == ntohs (TYPE_HOST))
+               {
+                       status = parse_part_string (&buffer, &buffer_len,
+                                       vl.host, sizeof (vl.host));
+               }
+               else if (header->type == ntohs (TYPE_PLUGIN))
+               {
+                       status = parse_part_string (&buffer, &buffer_len,
+                                       vl.plugin, sizeof (vl.plugin));
+               }
+               else if (header->type == ntohs (TYPE_PLUGIN_INSTANCE))
+               {
+                       status = parse_part_string (&buffer, &buffer_len,
+                                       vl.plugin_instance, sizeof (vl.plugin_instance));
+               }
+               else if (header->type == ntohs (TYPE_TYPE))
+               {
+                       status = parse_part_string (&buffer, &buffer_len,
+                                       type, sizeof (type));
+               }
+               else if (header->type == ntohs (TYPE_TYPE_INSTANCE))
+               {
+                       status = parse_part_string (&buffer, &buffer_len,
+                                       vl.type_instance, sizeof (vl.type_instance));
+               }
+               else
+               {
+                       DBG ("Unknown part type: 0x%0hx", header->type);
+                       buffer = ((char *) buffer) + header->length;
+               }
+       } /* while (buffer_len > sizeof (part_header_t)) */
+
+       return (0);
+} /* int parse_packet */
+
+static void free_sockent (sockent_t *se)
+{
+       sockent_t *next;
+       while (se != NULL)
+       {
+               next = se->next;
+               free (se->addr);
+               free (se);
+               se = next;
+       }
+} /* void free_sockent */
+
+/*
+ * int network_set_ttl
+ *
+ * Set the `IP_MULTICAST_TTL', `IP_TTL', `IPV6_MULTICAST_HOPS' or
+ * `IPV6_UNICAST_HOPS', depending on which option is applicable.
+ *
+ * The `struct addrinfo' is used to destinguish between unicast and multicast
+ * sockets.
+ */
+static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
+{
+       if ((network_config_ttl < 1) || (network_config_ttl > 255))
+               return (-1);
+
+       DBG ("ttl = %i", network_config_ttl);
 
        if (ai->ai_family == AF_INET)
        {
@@ -91,7 +499,8 @@ static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
                        optname = IP_TTL;
 
                if (setsockopt (se->fd, IPPROTO_IP, optname,
-                                       &ttl_int, sizeof (ttl_int)) == -1)
+                                       &network_config_ttl,
+                                       sizeof (network_config_ttl)) == -1)
                {
                        syslog (LOG_ERR, "setsockopt: %s", strerror (errno));
                        return (-1);
@@ -109,7 +518,8 @@ static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
                        optname = IPV6_UNICAST_HOPS;
 
                if (setsockopt (se->fd, IPPROTO_IPV6, optname,
-                                       &ttl_int, sizeof (ttl_int)) == -1)
+                                       &network_config_ttl,
+                                       sizeof (network_config_ttl)) == -1)
                {
                        syslog (LOG_ERR, "setsockopt: %s", strerror (errno));
                        return (-1);
@@ -117,7 +527,7 @@ static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
        }
 
        return (0);
-}
+} /* int network_set_ttl */
 
 static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
 {
@@ -200,31 +610,21 @@ static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
        }
 
        return (0);
-}
+} /* int network_bind_socket */
 
-int network_create_socket (const char *node, const char *service)
+static sockent_t *network_create_socket (const char *node,
+               const char *service,
+               int listen)
 {
-       sockent_t *socklist_tail;
-
        struct addrinfo  ai_hints;
        struct addrinfo *ai_list, *ai_ptr;
        int              ai_return;
 
-       int num_added = 0;
+       sockent_t *se_head = NULL;
+       sockent_t *se_tail = NULL;
 
        DBG ("node = %s, service = %s", node, service);
 
-       if (operating_mode == MODE_LOCAL || operating_mode == MODE_LOG)
-       {
-               syslog (LOG_WARNING, "network_create_socket: There is no point opening a socket when you are in mode `%s'.",
-                               operating_mode == MODE_LOCAL ? "Local" : "Log");
-               return (-1);
-       }
-
-       socklist_tail = socklist_head;
-       while ((socklist_tail != NULL) && (socklist_tail->next != NULL))
-               socklist_tail = socklist_tail->next;
-
        memset (&ai_hints, '\0', sizeof (ai_hints));
        ai_hints.ai_flags    = 0;
 #ifdef AI_PASSIVE
@@ -233,17 +633,20 @@ int network_create_socket (const char *node, const char *service)
 #ifdef AI_ADDRCONFIG
        ai_hints.ai_flags |= AI_ADDRCONFIG;
 #endif
-       ai_hints.ai_family   = PF_UNSPEC;
+       ai_hints.ai_family   = AF_UNSPEC;
        ai_hints.ai_socktype = SOCK_DGRAM;
        ai_hints.ai_protocol = IPPROTO_UDP;
 
-       if ((ai_return = getaddrinfo (node, service, &ai_hints, &ai_list)) != 0)
+       ai_return = getaddrinfo (node, service, &ai_hints, &ai_list);
+       if (ai_return != 0)
        {
                syslog (LOG_ERR, "getaddrinfo (%s, %s): %s",
-                               node == NULL ? "(null)" : node,
-                               service == NULL ? "(null)" : service,
-                               ai_return == EAI_SYSTEM ? strerror (errno) : gai_strerror (ai_return));
-               return (-1);
+                               (node == NULL) ? "(null)" : node,
+                               (service == NULL) ? "(null)" : service,
+                               (ai_return == EAI_SYSTEM)
+                               ? strerror (errno)
+                               : gai_strerror (ai_return));
+               return (NULL);
        }
 
        for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
@@ -268,8 +671,9 @@ int network_create_socket (const char *node, const char *service)
                memcpy (se->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
                se->addrlen = ai_ptr->ai_addrlen;
 
-               se->mode = operating_mode;
-               se->fd   = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
+               se->fd   = socket (ai_ptr->ai_family,
+                               ai_ptr->ai_socktype,
+                               ai_ptr->ai_protocol);
                se->next = NULL;
 
                if (se->fd == -1)
@@ -280,7 +684,7 @@ int network_create_socket (const char *node, const char *service)
                        continue;
                }
 
-               if (operating_mode == MODE_SERVER)
+               if (listen != 0)
                {
                        if (network_bind_socket (se, ai_ptr) != 0)
                        {
@@ -290,260 +694,417 @@ int network_create_socket (const char *node, const char *service)
                                continue;
                        }
                }
-               else if (operating_mode == MODE_CLIENT)
+               else /* listen == 0 */
                {
                        network_set_ttl (se, ai_ptr);
                }
 
-               if (socklist_tail == NULL)
+               if (se_tail == NULL)
                {
-                       socklist_head = se;
-                       socklist_tail = se;
+                       se_head = se;
+                       se_tail = se;
                }
                else
                {
-                       socklist_tail->next = se;
-                       socklist_tail = se;
+                       se_tail->next = se;
+                       se_tail = se;
                }
 
-               num_added++;
-
                /* We don't open more than one write-socket per node/service pair.. */
-               if (operating_mode == MODE_CLIENT)
+               if (listen == 0)
                        break;
        }
 
        freeaddrinfo (ai_list);
 
-       return (num_added);
-}
+       return (se_head);
+} /* sockent_t *network_create_socket */
 
-static int network_connect_default (void)
+static sockent_t *network_create_default_socket (int listen)
 {
-       int ret;
+       sockent_t *se_ptr  = NULL;
+       sockent_t *se_head = NULL;
+       sockent_t *se_tail = NULL;
 
-       if (socklist_head != NULL)
-               return (0);
+       se_ptr = network_create_socket (NET_DEFAULT_V6_ADDR,
+                       NET_DEFAULT_PORT, listen);
 
-       DBG ("socklist_head is NULL");
+       /* Don't send to the same machine in IPv6 and IPv4 if both are available. */
+       if ((listen == 0) && (se_ptr != NULL))
+               return (se_ptr);
+
+       if (se_ptr != NULL)
+       {
+               se_head = se_ptr;
+               se_tail = se_ptr;
+               while (se_tail->next != NULL)
+                       se_tail = se_tail->next;
+       }
 
-       ret = 0;
+       se_ptr = network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT, listen);
 
-       if (network_create_socket (NET_DEFAULT_V6_ADDR, NET_DEFAULT_PORT) > 0)
-               ret++;
+       if (se_tail == NULL)
+               return (se_ptr);
 
-       /* Don't use IPv4 and IPv6 in parallel by default.. */
-       if ((operating_mode == MODE_CLIENT) && (ret != 0))
-               return (ret);
+       se_tail->next = se_ptr;
+       return (se_head);
+} /* sockent_t *network_create_default_socket */
 
-       if (network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT) > 0)
-               ret++;
+static int network_add_listen_socket (const char *node, const char *service)
+{
+       sockent_t *se;
+       sockent_t *se_ptr;
+       int se_num = 0;
 
-       if (ret == 0)
-               ret = -1;
+       if (service == NULL)
+               service = NET_DEFAULT_PORT;
 
-       return (ret);
-}
+       if (node == NULL)
+               se = network_create_default_socket (1 /* listen == true */);
+       else
+               se = network_create_socket (node, service, 1 /* listen == true */);
 
-static int network_get_listen_socket (void)
-{
-       int fd;
-       int max_fd;
-       int status;
+       if (se == NULL)
+               return (-1);
 
-       fd_set readfds;
-       sockent_t *se;
+       for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
+               se_num++;
 
-       if (socklist_head == NULL)
-               network_connect_default ();
+       listen_sockets = (struct pollfd *) realloc (listen_sockets,
+                       (listen_sockets_num + se_num)
+                       * sizeof (struct pollfd));
 
-       FD_ZERO (&readfds);
-       max_fd = -1;
-       for (se = socklist_head; se != NULL; se = se->next)
+       for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
        {
-               if (se->mode != operating_mode)
-                       continue;
+               listen_sockets[listen_sockets_num].fd = se_ptr->fd;
+               listen_sockets[listen_sockets_num].events = POLLIN | POLLPRI;
+               listen_sockets[listen_sockets_num].revents = 0;
+               listen_sockets_num++;
+       } /* for (se) */
 
-               FD_SET (se->fd, &readfds);
-               if (se->fd >= max_fd)
-                       max_fd = se->fd + 1;
-       }
+       free_sockent (se);
+       return (0);
+} /* int network_add_listen_socket */
 
-       if (max_fd == -1)
-       {
-               syslog (LOG_WARNING, "No listen sockets found!");
+static int network_add_sending_socket (const char *node, const char *service)
+{
+       sockent_t *se;
+       sockent_t *se_ptr;
+
+       if (service == NULL)
+               service = NET_DEFAULT_PORT;
+
+       if (node == NULL)
+               se = network_create_default_socket (0 /* listen == false */);
+       else
+               se = network_create_socket (node, service, 0 /* listen == false */);
+
+       if (se == NULL)
                return (-1);
+
+       if (sending_sockets == NULL)
+       {
+               sending_sockets = se;
+               return (0);
        }
 
-       status = select (max_fd, &readfds, NULL, NULL, NULL);
+       for (se_ptr = sending_sockets; se_ptr->next != NULL; se_ptr = se_ptr->next)
+               /* seek end */;
+
+       se_ptr->next = se;
+       return (0);
+} /* int network_get_listen_socket */
 
-       if (status == -1)
+int network_receive (void)
+{
+       char buffer[BUFF_SIZE];
+       int  buffer_len;
+
+       int i;
+       int status;
+
+       if (listen_sockets_num == 0)
+               network_add_listen_socket (NULL, NULL);
+
+       if (listen_sockets_num == 0)
        {
-               if (errno != EINTR)
-                       syslog (LOG_ERR, "select: %s", strerror (errno));
+               syslog (LOG_ERR, "network: Failed to open a listening socket.");
                return (-1);
        }
 
-       fd = -1;
-       for (se = socklist_head; se != NULL; se = se->next)
+       while (listen_loop == 0)
        {
-               if (se->mode != operating_mode)
-                       continue;
+               status = poll (listen_sockets, listen_sockets_num, -1);
 
-               if (FD_ISSET (se->fd, &readfds))
+               if (status <= 0)
                {
-                       fd = se->fd;
-                       break;
+                       if (errno == EINTR)
+                               continue;
+                       syslog (LOG_ERR, "poll failed: %s",
+                                       strerror (errno));
+                       return (-1);
                }
-       }
 
-       if (fd == -1)
-               syslog (LOG_WARNING, "No socket ready..?");
+               for (i = 0; (i < listen_sockets_num) && (status > 0); i++)
+               {
+                       if ((listen_sockets[i].revents & (POLLIN | POLLPRI)) == 0)
+                               continue;
+                       status--;
+
+                       buffer_len = recv (listen_sockets[i].fd,
+                                       buffer, sizeof (buffer),
+                                       0 /* no flags */);
+                       if (buffer_len < 0)
+                       {
+                               syslog (LOG_ERR, "recv failed: %s", strerror (errno));
+                               return (-1);
+                       }
+
+                       parse_packet (buffer, buffer_len);
+               } /* for (listen_sockets) */
+       } /* while (listen_loop == 0) */
 
-       DBG ("fd = %i", fd);
-       return (fd);
+       return (0);
 }
 
-int network_receive (char **host, char **type, char **inst, char **value)
+static void *receive_thread (void *arg)
 {
-       int fd;
-       char buffer[BUFF_SIZE];
+       return (network_receive () ? (void *) 1 : (void *) 0);
+} /* void *receive_thread */
 
-       struct sockaddr_storage addr;
-       socklen_t               addrlen;
+static void network_send_buffer (const char *buffer, int buffer_len)
+{
+       sockent_t *se;
        int status;
 
-       char *fields[4];
+       DBG ("buffer_len = %i", buffer_len);
 
-       assert (operating_mode == MODE_SERVER);
-
-       *host  = NULL;
-       *type  = NULL;
-       *inst  = NULL;
-       *value = NULL;
+       for (se = sending_sockets; se != NULL; se = se->next)
+       {
+               while (42)
+               {
+                       status = sendto (se->fd, buffer, buffer_len, 0 /* no flags */,
+                                       (struct sockaddr *) se->addr, se->addrlen);
+                       if (status < 0)
+                       {
+                               if (errno == EINTR)
+                                       continue;
+                               syslog (LOG_ERR, "network plugin: sendto failed: %s",
+                                               strerror (errno));
+                               break;
+                       }
 
-       if ((fd = network_get_listen_socket ()) < 0)
-               return (-1);
+                       break;
+               } /* while (42) */
+       } /* for (sending_sockets) */
+} /* void network_send_buffer */
 
-       addrlen = sizeof (addr);
-       if (recvfrom (fd, buffer, BUFF_SIZE, 0, (struct sockaddr *) &addr, &addrlen) == -1)
+static int add_to_buffer (char *buffer, int buffer_size,
+               value_list_t *vl_def, char *type_def,
+               const data_set_t *ds, const value_list_t *vl)
+{
+       if (strcmp (vl_def->host, vl->host) != 0)
        {
-               syslog (LOG_ERR, "recvfrom: %s", strerror (errno));
-               return (-1);
+               if (write_part_string (&buffer, &buffer_size, TYPE_HOST,
+                                       vl->host, strlen (vl->host)) != 0)
+                       return (-1);
+               strcpy (vl_def->host, vl->host);
+               DBG ("host = %s", vl->host);
        }
 
-       if ((*host = (char *) malloc (BUFF_SIZE)) == NULL)
+       if (vl_def->time != vl->time)
        {
-               syslog (LOG_EMERG, "malloc: %s", strerror (errno));
-               return (-1);
+               if (write_part_number (&buffer, &buffer_size, TYPE_TIME,
+                                       (uint64_t) vl->time))
+                       return (-1);
+               vl_def->time = vl->time;
+               DBG ("time = %u", (unsigned int) vl->time);
        }
 
-       status = getnameinfo ((struct sockaddr *) &addr, addrlen,
-                       *host, BUFF_SIZE, NULL, 0, 0);
-       if (status != 0)
+       if (strcmp (vl_def->plugin, vl->plugin) != 0)
        {
-               free (*host); *host = NULL;
-               syslog (LOG_ERR, "getnameinfo: %s",
-                               status == EAI_SYSTEM ? strerror (errno) : gai_strerror (status));
-               return (-1);
+               if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN,
+                                       vl->plugin, strlen (vl->plugin)) != 0)
+                       return (-1);
+               strcpy (vl_def->plugin, vl->plugin);
+               DBG ("plugin = %s", vl->plugin);
        }
 
-       if (strsplit (buffer, fields, 4) != 3)
+       if (strcmp (vl_def->plugin_instance, vl->plugin_instance) != 0)
        {
-               syslog (LOG_WARNING, "Invalid message from `%s'", *host);
-               free (*host); *host = NULL;
-               return (1);
+               if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE,
+                                       vl->plugin_instance,
+                                       strlen (vl->plugin_instance)) != 0)
+                       return (-1);
+               strcpy (vl_def->plugin_instance, vl->plugin_instance);
+               DBG ("plugin_instance = %s", vl->plugin_instance);
        }
 
-       if ((*type = strdup (fields[0])) == NULL)
+       if (strcmp (type_def, ds->type) != 0)
        {
-               syslog (LOG_EMERG, "strdup: %s", strerror (errno));
-               free (*host); *host = NULL;
-               return (-1);
+               if (write_part_string (&buffer, &buffer_size, TYPE_TYPE,
+                                       ds->type, strlen (ds->type)) != 0)
+                       return (-1);
+               strcpy (type_def, ds->type);
+               DBG ("type = %s", ds->type);
        }
 
-       if ((*inst = strdup (fields[1])) == NULL)
+       if (strcmp (vl_def->type_instance, vl->type_instance) != 0)
        {
-               syslog (LOG_EMERG, "strdup: %s", strerror (errno));
-               free (*host); *host = NULL;
-               free (*type); *type = NULL;
+               if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE,
+                                       vl->type_instance,
+                                       strlen (vl->type_instance)) != 0)
+                       return (-1);
+               strcpy (vl_def->type_instance, vl->type_instance);
+               DBG ("type_instance = %s", vl->type_instance);
+       }
+       
+       if (write_part_values (&buffer, &buffer_size, ds, vl) != 0)
                return (-1);
+
+       return (buffer_size);
+} /* int add_to_buffer */
+
+static void flush_buffer (void)
+{
+       network_send_buffer (send_buffer, send_buffer_fill);
+       send_buffer_ptr  = send_buffer;
+       send_buffer_fill = 0;
+       memset (&send_buffer_vl, '\0', sizeof (send_buffer_vl));
+       memset (send_buffer_type, '\0', sizeof (send_buffer_type));
+}
+
+static int network_write (const data_set_t *ds, const value_list_t *vl)
+{
+       int status;
+       /* TODO: lock buffer */
+       status = add_to_buffer (send_buffer_ptr,
+                       sizeof (send_buffer) - send_buffer_fill,
+                       &send_buffer_vl, send_buffer_type,
+                       ds, vl);
+       if (status >= 0)
+       {
+               send_buffer_fill += status;
+               send_buffer_ptr  += status;
+       }
+       else
+       {
+               flush_buffer ();
+
+               status = add_to_buffer (send_buffer_ptr,
+                               sizeof (send_buffer) - send_buffer_fill,
+                               &send_buffer_vl, send_buffer_type,
+                               ds, vl);
+
+               if (status >= 0)
+               {
+                       send_buffer_fill += status;
+                       send_buffer_ptr  += status;
+               }
        }
 
-       if ((*value = strdup (fields[2])) == NULL)
+       if (status < 0)
        {
-               syslog (LOG_EMERG, "strdup: %s", strerror (errno));
-               free (*host); *host = NULL;
-               free (*type); *type = NULL;
-               free (*inst); *inst = NULL;
-               return (-1);
+               syslog (LOG_ERR, "network plugin: Unable to append to the "
+                               "buffer for some weird reason");
+       }
+       else if ((sizeof (send_buffer) - send_buffer_fill) < 15)
+       {
+               flush_buffer ();
        }
+       /* TODO: unlock buffer */
 
-       DBG ("host = %s, type = %s, inst = %s, value = %s",
-                       *host, *type, *inst, *value);
+       return ((status < 0) ? -1 : 0);
+} /* int network_write */
 
+static int network_config (const char *key, const char *val)
+{
+       char *node;
+       char *service;
+
+       char *fields[3];
+       int   fields_num;
+
+       if ((strcasecmp ("Listen", key) == 0)
+                       || (strcasecmp ("Server", key) == 0))
+       {
+               char *val_cpy = strdup (val);
+               if (val_cpy == NULL)
+                       return (1);
+
+               service = NET_DEFAULT_PORT;
+               fields_num = strsplit (val_cpy, fields, 3);
+               if ((fields_num != 1)
+                               && (fields_num != 2))
+                       return (1);
+               else if (fields_num == 2)
+                       service = fields[1];
+               node = fields[0];
+
+               if (strcasecmp ("Listen", key) == 0)
+                       network_add_listen_socket (node, service);
+               else
+                       network_add_sending_socket (node, service);
+       }
+       else if (strcasecmp ("TimeToLive", key) == 0)
+       {
+               int tmp = atoi (val);
+               if ((tmp > 0) && (tmp < 256))
+                       network_config_ttl = tmp;
+               else
+                       return (1);
+       }
+       else
+       {
+               return (-1);
+       }
        return (0);
 }
 
-int network_send (char *type, char *inst, char *value)
+static int network_shutdown (void)
 {
-       char buf[BUFF_SIZE];
-       int buflen;
+       DBG ("Shutting down.");
 
-       sockent_t *se;
+       listen_loop++;
 
-       int ret;
-       int status;
+       pthread_kill (listen_thread, SIGTERM);
+       pthread_join (listen_thread, NULL /* no return value */);
 
-       DBG ("type = %s, inst = %s, value = %s", type, inst, value);
+       listen_thread = 0;
 
-       assert (operating_mode == MODE_CLIENT);
+       return (0);
+}
 
-       buflen = snprintf (buf, BUFF_SIZE, "%s %s %s", type, inst, value);
-       if ((buflen >= BUFF_SIZE) || (buflen < 1))
-       {
-               syslog (LOG_WARNING, "network_send: snprintf failed..");
-               return (-1);
-       }
-       buf[buflen] = '\0';
-       buflen++;
+static int network_init (void)
+{
+       plugin_register_shutdown ("network", network_shutdown);
+
+       send_buffer_ptr  = send_buffer;
+       send_buffer_fill = 0;
+       memset (&send_buffer_vl, '\0', sizeof (send_buffer_vl));
+       memset (send_buffer_type, '\0', sizeof (send_buffer_type));
 
-       if (socklist_head == NULL)
-               network_connect_default ();
+       /* setup socket(s) and so on */
+       if (sending_sockets != NULL)
+               plugin_register_write ("network", network_write);
 
-       ret = 0;
-       for (se = socklist_head; se != NULL; se = se->next)
+       if ((listen_sockets_num != 0) && (listen_thread == 0))
        {
-               if (se->mode != operating_mode)
-                       continue;
+               int status;
 
-               while (1)
-               {
-                       status = sendto (se->fd, buf, buflen, 0,
-                                       (struct sockaddr *) se->addr, se->addrlen);
+               status = pthread_create (&listen_thread, NULL /* no attributes */,
+                               receive_thread, NULL /* no argument */);
 
-                       if (status == -1)
-                       {
-                               if (errno == EINTR)
-                               {
-                                       DBG ("sendto was interrupted");
-                                       continue;
-                               }
-                               else
-                               {
-                                       syslog (LOG_ERR, "sendto: %s", strerror (errno));
-                                       ret = -1;
-                                       break;
-                               }
-                       }
-                       else if (ret >= 0)
-                               ret++;
-                       break;
-               }
+               if (status != 0)
+                       syslog (LOG_ERR, "network: pthread_create failed: %s",
+                                       strerror (errno));
        }
+       return (0);
+} /* int network_init */
 
-       if (ret == 0)
-               syslog (LOG_WARNING, "Message wasn't sent to anybody..");
-
-       return (ret);
+void module_register (void)
+{
+       plugin_register_config ("network", network_config,
+                       config_keys, config_keys_num);
+       plugin_register_init   ("network", network_init);
 }
index 2df989b..b20fc75 100644 (file)
@@ -4,8 +4,7 @@
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 #define NET_DEFAULT_V6_ADDR "ff18::efc0:4a42"
 #define NET_DEFAULT_PORT    "25826"
 
-int network_create_socket (const char *node, const char *service);
-int network_receive (char **host, char **type, char **instance, char **value);
-int network_send (char *type, char *instance, char *value);
+#define TYPE_HOST            0x0000
+#define TYPE_TIME            0x0001
+#define TYPE_PLUGIN          0x0002
+#define TYPE_PLUGIN_INSTANCE 0x0003
+#define TYPE_TYPE            0x0004
+#define TYPE_TYPE_INSTANCE   0x0005
+#define TYPE_VALUES          0x0006
 
 #endif /* NETWORK_H */
index d0f33c5..004c8f5 100644 (file)
--- a/src/nfs.c
+++ b/src/nfs.c
@@ -4,8 +4,7 @@
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -24,6 +23,7 @@
 #include "collectd.h"
 #include "common.h"
 #include "plugin.h"
+#include "utils_debug.h"
 
 #define MODULE_NAME "nfs"
 
@@ -34,9 +34,6 @@
 # define NFS_HAVE_READ 0
 #endif
 
-static char *nfs2_procedures_file  = "nfs2_procedures-%s.rrd";
-static char *nfs3_procedures_file  = "nfs3_procedures-%s.rrd";
-
 /*
 see /proc/net/rpc/nfs
 see http://www.missioncriticallinux.com/orph/NFS-Statistics
@@ -82,57 +79,68 @@ Number      Procedures  Procedures
 21                      commit
 */
 
-static char *nfs2_procedures_ds_def[] =
+static data_source_t procedure_dsrc[1] =
+{
+       {"value", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t procedure_ds =
 {
-       "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:root:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:wrcache:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "nfs_procedure", 1, procedure_dsrc
+};
+
+#if NFS_HAVE_READ
+static const char *nfs2_procedures_names[] =
+{
+       "null",
+       "getattr",
+       "setattr",
+       "root",
+       "lookup",
+       "readlink",
+       "read",
+       "wrcache",
+       "write",
+       "create",
+       "remove",
+       "rename",
+       "link",
+       "symlink",
+       "mkdir",
+       "rmdir",
+       "readdir",
+       "fsstat",
        NULL
 };
-static int nfs2_procedures_ds_num = 18;
+static int nfs2_procedures_names_num = 18;
 
-static char *nfs3_procedures_ds_def[] =
+static const char *nfs3_procedures_names[] =
 {
-       "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:access:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:mknod:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:readdirplus:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:fsinfo:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:pathconf:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:commit:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "null",
+       "getattr",
+       "setattr",
+       "lookup",
+       "access",
+       "readlink",
+       "read",
+       "write",
+       "create",
+       "mkdir",
+       "symlink",
+       "mknod",
+       "remove",
+       "rmdir",
+       "rename",
+       "link",
+       "readdir",
+       "readdirplus",
+       "fsstat",
+       "fsinfo",
+       "pathconf",
+       "commit",
        NULL
 };
-static int nfs3_procedures_ds_num = 22;
+static int nfs3_procedures_names_num = 22;
 
 #if HAVE_LIBKSTAT && 0
 extern kstat_ctl_t *kc;
@@ -146,7 +154,8 @@ static kstat_t *nfs4_ksp_server;
 
 /* Possibly TODO: NFSv4 statistics */
 
-static void nfs_init (void)
+#if 0
+static int nfs_init (void)
 {
 #if HAVE_LIBKSTAT && 0
        kstat_t *ksp_chain;
@@ -181,89 +190,45 @@ static void nfs_init (void)
        }
 #endif
 
-       return;
-}
+       return (0);
+} /* int nfs_init */
+#endif
 
 #define BUFSIZE 1024
-static void nfs2_procedures_write (char *host, char *inst, char *val)
-{
-       char filename[BUFSIZE];
-
-       if (snprintf (filename, BUFSIZE, nfs2_procedures_file, inst) > BUFSIZE)
-               return;
-
-       rrd_update_file (host, filename, val, nfs2_procedures_ds_def,
-                       nfs2_procedures_ds_num);
-}
-
-static void nfs3_procedures_write (char *host, char *inst, char *val)
-{
-       char filename[BUFSIZE];
-
-       if (snprintf (filename, BUFSIZE, nfs3_procedures_file, inst) > BUFSIZE)
-               return;
-
-       rrd_update_file (host, filename, val, nfs3_procedures_ds_def,
-                       nfs3_procedures_ds_num);
-}
-
-#if NFS_HAVE_READ
-static void nfs2_procedures_submit (unsigned long long *val, char *inst)
-{
-       char buf[BUFSIZE];
-       int retval = 0;
-
-       retval = snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:"
-                       "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:"
-                       "%llu:%llu:%llu", /* 18x %llu */
-                       (unsigned int) curtime,
-                       val[0], val[1], val[2], val[3], val[4], val[5], val[6],
-                       val[7], val[8], val[9], val[10], val[11], val[12],
-                       val[13], val[14], val[15], val[16], val[17]);
-
-
-       if (retval >= BUFSIZE)
-               return;
-       else if (retval < 0)
-       {
-               syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno));
-               return;
-       }
-
-       plugin_submit ("nfs2_procedures", inst, buf);
-}
-
-static void nfs3_procedures_submit (unsigned long long *val, char *inst)
+static void nfs_procedures_submit (const char *plugin_instance,
+               unsigned long long *val, const char **names, int len)
 {
-       char buf[BUFSIZE];
-       int retval = 0;
-
-       retval = snprintf(buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:"
-                       "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:"
-                       "%llu:%llu:%llu:%llu:%llu:%llu:%llu", /* 22x %llu */
-                       (unsigned int) curtime,
-                       val[0], val[1], val[2], val[3], val[4], val[5], val[6],
-                       val[7], val[8], val[9], val[10], val[11], val[12],
-                       val[13], val[14], val[15], val[16], val[17], val[18],
-                       val[19], val[20], val[21]);
-
-       if (retval >= BUFSIZE)
-               return;
-       else if (retval < 0)
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+       int i;
+
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "nfs");
+       strncpy (vl.plugin_instance, plugin_instance,
+                       sizeof (vl.plugin_instance));
+
+       for (i = 0; i < len; i++)
        {
-               syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno));
-               return;
+               values[0].counter = val[i];
+               strncpy (vl.type_instance, names[i],
+                               sizeof (vl.type_instance));
+               DBG ("%s-%s/nfs_procedure-%s = %llu",
+                               vl.plugin, vl.plugin_instance,
+                               vl.type_instance, val[i]);
+               plugin_dispatch_values ("nfs_procedure", &vl);
        }
-
-       plugin_submit("nfs3_procedures", inst, buf);
-}
-#endif /* NFS_HAVE_READ */
+} /* void nfs_procedures_submit */
 
 #if KERNEL_LINUX
 static void nfs_read_stats_file (FILE *fh, char *inst)
 {
        char buffer[BUFSIZE];
 
+       char plugin_instance[DATA_MAX_NAME_LEN];
+
        char *fields[48];
        int numfields = 0;
 
@@ -274,30 +239,44 @@ static void nfs_read_stats_file (FILE *fh, char *inst)
        {
                numfields = strsplit (buffer, fields, 48);
 
-               if (numfields < 2)
+               if (((numfields - 2) != nfs2_procedures_names_num)
+                               && ((numfields - 2)
+                                       != nfs3_procedures_names_num))
                        continue;
 
-               if (strncmp (fields[0], "proc2", 5) == 0)
+               if (strcmp (fields[0], "proc2") == 0)
                {
                        int i;
                        unsigned long long *values;
 
-                       if (numfields - 2 != nfs2_procedures_ds_num)
+                       if ((numfields - 2) != nfs2_procedures_names_num)
                        {
-                               syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS2 statistics.", numfields - 2);
+                               syslog (LOG_WARNING, "nfs plugin: Wrong "
+                                               "number of fields (= %i) "
+                                               "for NFSv2 statistics.",
+                                               numfields - 2);
                                continue;
                        }
 
-                       if ((values = (unsigned long long *) malloc (nfs2_procedures_ds_num * sizeof (unsigned long long))) == NULL)
+                       snprintf (plugin_instance, sizeof (plugin_instance),
+                                       "v2%s", inst);
+                       plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
+
+                       values = (unsigned long long *) malloc (nfs2_procedures_names_num * sizeof (unsigned long long));
+                       if (values == NULL)
                        {
-                               syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno));
+                               syslog (LOG_ERR, "nfs plugin: malloc "
+                                               "failed: %s",
+                                               strerror (errno));
                                continue;
                        }
 
-                       for (i = 0; i < nfs2_procedures_ds_num; i++)
+                       for (i = 0; i < nfs2_procedures_names_num; i++)
                                values[i] = atoll (fields[i + 2]);
 
-                       nfs2_procedures_submit (values, inst);
+                       nfs_procedures_submit (plugin_instance, values,
+                                       nfs2_procedures_names,
+                                       nfs2_procedures_names_num);
 
                        free (values);
                }
@@ -306,27 +285,39 @@ static void nfs_read_stats_file (FILE *fh, char *inst)
                        int i;
                        unsigned long long *values;
 
-                       if (numfields - 2 != nfs3_procedures_ds_num)
+                       if ((numfields - 2) != nfs3_procedures_names_num)
                        {
-                               syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS3 statistics.", numfields - 2);
+                               syslog (LOG_WARNING, "nfs plugin: Wrong "
+                                               "number of fields (= %i) "
+                                               "for NFSv3 statistics.",
+                                               numfields - 2);
                                continue;
                        }
 
-                       if ((values = (unsigned long long *) malloc (nfs3_procedures_ds_num * sizeof (unsigned long long))) == NULL)
+                       snprintf (plugin_instance, sizeof (plugin_instance),
+                                       "v3%s", inst);
+                       plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
+
+                       values = (unsigned long long *) malloc (nfs3_procedures_names_num * sizeof (unsigned long long));
+                       if (values == NULL)
                        {
-                               syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno));
+                               syslog (LOG_ERR, "nfs plugin: malloc "
+                                               "failed: %s",
+                                               strerror (errno));
                                continue;
                        }
 
-                       for (i = 0; i < nfs3_procedures_ds_num; i++)
+                       for (i = 0; i < nfs3_procedures_names_num; i++)
                                values[i] = atoll (fields[i + 2]);
 
-                       nfs3_procedures_submit (values, inst);
+                       nfs_procedures_submit (plugin_instance, values,
+                                       nfs3_procedures_names,
+                                       nfs3_procedures_names_num);
 
                        free (values);
                }
-       }
-}
+       } /* while (fgets (buffer, BUFSIZE, fh) != NULL) */
+} /* void nfs_read_stats_file */
 #endif /* defined(KERNEL_LINUX) */
 #undef BUFSIZE
 
@@ -358,8 +349,7 @@ static void nfs2_read_kstat (kstat_t *ksp, char *inst)
 }
 #endif
 
-#if NFS_HAVE_READ
-static void nfs_read (void)
+static int nfs_read (void)
 {
 #if KERNEL_LINUX
        FILE *fh;
@@ -384,16 +374,18 @@ static void nfs_read (void)
        if (nfs2_ksp_server != NULL)
                nfs2_read_kstat (nfs2_ksp_server, "server");
 #endif /* defined(HAVE_LIBKSTAT) */
+
+       return (0);
 }
-#else
-# define nfs_read NULL
 #endif /* NFS_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, nfs_init, nfs_read, NULL);
-       plugin_register ("nfs2_procedures", NULL, NULL, nfs2_procedures_write);
-       plugin_register ("nfs3_procedures", NULL, NULL, nfs3_procedures_write);
+       plugin_register_data_set (&procedure_ds);
+
+#if NFS_HAVE_READ
+       plugin_register_read ("nfs", nfs_read);
+#endif
 }
 
 #undef MODULE_NAME
index b65a9e8..e4a230b 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/ntpd.c
- * Copyright (C) 2006  Florian octo Forster
+ * Copyright (C) 2006-2007  Florian octo Forster
  *
  * 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
@@ -25,8 +25,6 @@
 #include "configfile.h"
 #include "utils_debug.h"
 
-#define MODULE_NAME "ntpd"
-
 #if HAVE_SYS_SOCKET_H
 # define NTPD_HAVE_READ 1
 #else
 #if HAVE_NETINET_TCP_H
 # include <netinet/tcp.h>
 #endif
-#if HAVE_SYS_POLL_H
-# include <sys/poll.h>
+#if HAVE_POLL_H
+# include <poll.h>
 #endif
 
-static char *config_keys[] =
+static data_source_t seconds_dsrc[1] =
 {
-       "Host",
-       "Port",
-       NULL
+       {"seconds", DS_TYPE_GAUGE, -1000000.0, 1000000.0}
+};
+
+static data_set_t time_offset_ds =
+{
+       "time_offset", 1, seconds_dsrc
 };
-static int config_keys_num = 2;
 
-/* drift */
-static char *time_offset_file     = "ntpd/time_offset-%s.rrd";
-static char *time_dispersion_file = "ntpd/time_dispersion-%s.rrd";
-static char *time_delay_file      = "ntpd/delay-%s.rrd";
+static data_set_t time_dispersion_ds =
+{
+       "time_dispersion", 1, seconds_dsrc
+};
 
-/* used for `time_offset', `time_dispersion', and `delay' */
-static char *sec_ds_def[] =
+static data_set_t delay_ds =
 {
-       "DS:seconds:GAUGE:"COLLECTD_HEARTBEAT":-1000000:1000000",
-       NULL
+       "delay", 1, seconds_dsrc
+};
+
+static data_source_t ppm_dsrc[1] =
+{
+       {"ppm", DS_TYPE_GAUGE, -1000000.0, 1000000.0}
 };
-static int sec_ds_num = 1;
 
-static char *frequency_offset_file = "ntpd/frequency_offset-%s.rrd";
-static char *frequency_offset_ds_def[] =
+static data_set_t frequency_offset_ds =
 {
-       "DS:ppm:GAUGE:"COLLECTD_HEARTBEAT":-1000000:1000000",
+       "frequency_offset", 1, ppm_dsrc
+};
+
+static const char *config_keys[] =
+{
+       "Host",
+       "Port",
        NULL
 };
-static int frequency_offset_ds_num = 1;
+static int config_keys_num = 2;
 
 #if NTPD_HAVE_READ
 # define NTPD_DEFAULT_HOST "localhost"
@@ -90,7 +97,6 @@ static int frequency_offset_ds_num = 1;
 static int   sock_descr = -1;
 static char *ntpd_host = NULL;
 static char *ntpd_port = NULL;
-#endif
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * The following definitions were copied from the NTPd distribution  *
@@ -286,7 +292,7 @@ static int refclock_names_num = 45;
  * End of the copied stuff..                                         *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-static int ntpd_config (char *key, char *value)
+static int ntpd_config (const char *key, const char *value)
 {
        if (strcasecmp (key, "host") == 0)
        {
@@ -310,64 +316,22 @@ static int ntpd_config (char *key, char *value)
        return (0);
 }
 
-static void ntpd_init (void)
+static void ntpd_submit (char *type, char *type_inst, double value)
 {
-       return;
-}
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-static void ntpd_write_sec (char *host, char *inst, char *val, char *file)
-{
-       char buf[256];
-       int  status;
+       values[0].gauge = value;
 
-       status = snprintf (buf, 256, file, inst);
-       if ((status < 1) || (status >= 256))
-               return;
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "ntpd");
+       strcpy (vl.plugin_instance, "");
+       strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 
-       rrd_update_file (host, buf, val,
-                       sec_ds_def, sec_ds_num);
-}
-
-static void ntpd_write_time_offset (char *host, char *inst, char *val)
-{
-       ntpd_write_sec (host, inst, val, time_offset_file);
-}
-
-static void ntpd_write_time_dispersion (char *host, char *inst, char *val)
-{
-       ntpd_write_sec (host, inst, val, time_dispersion_file);
-}
-
-static void ntpd_write_delay (char *host, char *inst, char *val)
-{
-       ntpd_write_sec (host, inst, val, time_delay_file);
-}
-
-static void ntpd_write_frequency_offset (char *host, char *inst, char *val)
-{
-       char buf[256];
-       int  status;
-
-       status = snprintf (buf, 256, frequency_offset_file, inst);
-       if ((status < 1) || (status >= 256))
-               return;
-
-       rrd_update_file (host, buf, val,
-                       frequency_offset_ds_def, frequency_offset_ds_num);
-}
-
-#if NTPD_HAVE_READ
-static void ntpd_submit (char *type, char *inst, double value)
-{
-       char buf[256];
-
-       if (snprintf (buf, 256, "%u:%.8f", (unsigned int) curtime, value) >= 256)
-               return;
-
-       DBG ("type = %s; inst = %s; value = %s;",
-                       type, inst, buf);
-
-       plugin_submit (type, inst, buf);
+       plugin_dispatch_values (type, &vl);
 }
 
 /* returns `tv0 - tv1' in milliseconds or 0 if `tv1 > tv0' */
@@ -810,7 +774,7 @@ static double ntpd_read_fp (int32_t val_int)
        return (val_double);
 }
 
-static void ntpd_read (void)
+static int ntpd_read (void)
 {
        struct info_kernel *ik;
        int                 ik_num;
@@ -835,13 +799,13 @@ static void ntpd_read (void)
        if (status != 0)
        {
                DBG ("ntpd_do_query failed with status %i", status);
-               return;
+               return (-1);
        }
        if ((ik == NULL) || (ik_num == 0) || (ik_size == 0))
        {
                DBG ("ntpd_do_query returned: ik = %p; ik_num = %i; ik_size = %i;",
                                (void *) ik, ik_num, ik_size);
-               return;
+               return (-1);
        }
 
        /* kerninfo -> estimated error */
@@ -854,9 +818,9 @@ static void ntpd_read (void)
                        ntpd_read_fp (ik->freq),
                        ntpd_read_fp (ik->esterror));
 
-       ntpd_submit ("ntpd_frequency_offset", "loop",  ntpd_read_fp (ik->freq));
-       ntpd_submit ("ntpd_time_offset",      "loop",  ntpd_read_fp (ik->offset));
-       ntpd_submit ("ntpd_time_offset",      "error", ntpd_read_fp (ik->esterror));
+       ntpd_submit ("frequency_offset", "loop",  ntpd_read_fp (ik->freq));
+       ntpd_submit ("time_offset",      "loop",  ntpd_read_fp (ik->offset));
+       ntpd_submit ("time_offset",      "error", ntpd_read_fp (ik->esterror));
 
        free (ik);
        ik = NULL;
@@ -868,13 +832,13 @@ static void ntpd_read (void)
        if (status != 0)
        {
                DBG ("ntpd_do_query failed with status %i", status);
-               return;
+               return (-1);
        }
        if ((ps == NULL) || (ps_num == 0) || (ps_size == 0))
        {
                DBG ("ntpd_do_query returned: ps = %p; ps_num = %i; ps_size = %i;",
                                (void *) ps, ps_num, ps_size);
-               return;
+               return (-1);
        }
 
        for (i = 0; i < ps_num; i++)
@@ -979,29 +943,28 @@ static void ntpd_read (void)
                                ntpd_read_fp (ptr->dispersion));
 
                if (refclock_id != 1) /* not the system clock (offset will always be zero.. */
-                       ntpd_submit ("ntpd_time_offset", peername, offset);
-               ntpd_submit ("ntpd_time_dispersion", peername, ntpd_read_fp (ptr->dispersion));
+                       ntpd_submit ("time_offset", peername, offset);
+               ntpd_submit ("time_dispersion", peername, ntpd_read_fp (ptr->dispersion));
                if (refclock_id == 0) /* not a reference clock */
-                       ntpd_submit ("ntpd_delay", peername, ntpd_read_fp (ptr->delay));
+                       ntpd_submit ("delay", peername, ntpd_read_fp (ptr->delay));
        }
 
        free (ps);
        ps = NULL;
 
-       return;
-}
-#else
-# define ntpd_read NULL
+       return (0);
+} /* int ntpd_read */
 #endif /* NTPD_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, ntpd_init, ntpd_read, NULL);
-       plugin_register ("ntpd_time_offset", NULL, NULL, ntpd_write_time_offset);
-       plugin_register ("ntpd_time_dispersion", NULL, NULL, ntpd_write_time_dispersion);
-       plugin_register ("ntpd_delay", NULL, NULL, ntpd_write_delay);
-       plugin_register ("ntpd_frequency_offset", NULL, NULL, ntpd_write_frequency_offset);
-       cf_register (MODULE_NAME, ntpd_config, config_keys, config_keys_num);
-}
+       plugin_register_data_set (&time_offset_ds);
+       plugin_register_data_set (&time_dispersion_ds);
+       plugin_register_data_set (&delay_ds);
+       plugin_register_data_set (&frequency_offset_ds);
 
-#undef MODULE_NAME
+#if NTPD_HAVE_READ
+       plugin_register_config ("ntpd", ntpd_config, config_keys, config_keys_num);
+       plugin_register_read ("ntpd", ntpd_read);
+#endif /* NTPD_HAVE_READ */
+}
index 2a2f03e..48cea55 100644 (file)
@@ -4,8 +4,7 @@
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 #include "configfile.h"
 #include "utils_debug.h"
 
-#define MODULE_NAME "ping"
-
 #include <netinet/in.h>
 #include "liboping/oping.h"
 
+/*
+ * Private data types
+ */
 struct hostlist_s
 {
        char *host;
@@ -40,19 +40,23 @@ struct hostlist_s
 };
 typedef struct hostlist_s hostlist_t;
 
+/*
+ * Private variables
+ */
 static pingobj_t *pingobj = NULL;
 static hostlist_t *hosts = NULL;
 
-static char *file_template = "ping-%s.rrd";
+static data_source_t dsrc[1] =
+{
+       {"ping", DS_TYPE_GAUGE, 0, 65535.0},
+};
 
-static char *ds_def[] = 
+static data_set_t ds =
 {
-       "DS:ping:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       NULL
+       "ping", 1, dsrc
 };
-static int ds_num = 1;
 
-static char *config_keys[] =
+static const char *config_keys[] =
 {
        "Host",
        "TTL",
@@ -60,6 +64,9 @@ static char *config_keys[] =
 };
 static int config_keys_num = 2;
 
+/*
+ * Private functions
+ */
 static void add_hosts (void)
 {
        hostlist_t *hl_this;
@@ -109,13 +116,15 @@ static void add_hosts (void)
        }
 }
 
-static void ping_init (void)
+static int ping_init (void)
 {
        if (hosts != NULL)
                add_hosts ();
+
+       return (0);
 }
 
-static int ping_config (char *key, char *value)
+static int ping_config (const char *key, const char *value)
 {
        if (pingobj == NULL)
        {
@@ -170,33 +179,25 @@ static int ping_config (char *key, char *value)
        return (0);
 }
 
-static void ping_write (char *host, char *inst, char *val)
-{
-       char file[512];
-       int status;
-
-       status = snprintf (file, 512, file_template, inst);
-       if (status < 1)
-               return;
-       else if (status >= 512)
-               return;
-
-       rrd_update_file (host, file, val, ds_def, ds_num);
-}
-
-#define BUFSIZE 256
 static void ping_submit (char *host, double latency)
 {
-       char buf[BUFSIZE];
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = latency;
 
-       if (snprintf (buf, BUFSIZE, "%u:%f", (unsigned int) curtime, latency) >= BUFSIZE)
-               return;
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "ping");
+       strcpy (vl.plugin_instance, "");
+       strncpy (vl.type_instance, host, sizeof (vl.type_instance));
 
-       plugin_submit (MODULE_NAME, host, buf);
+       plugin_dispatch_values ("ping", &vl);
 }
-#undef BUFSIZE
 
-static void ping_read (void)
+static int ping_read (void)
 {
        pingobj_iter_t *iter;
 
@@ -205,7 +206,7 @@ static void ping_read (void)
        size_t buf_len;
 
        if (pingobj == NULL)
-               return;
+               return (-1);
 
        if (hosts != NULL)
                add_hosts ();
@@ -214,7 +215,7 @@ static void ping_read (void)
        {
                syslog (LOG_ERR, "ping: `ping_send' failed: %s",
                                ping_get_error (pingobj));
-               return;
+               return (-1);
        }
 
        for (iter = ping_iterator_get (pingobj);
@@ -234,12 +235,14 @@ static void ping_read (void)
                DBG ("host = %s, latency = %f", host, latency);
                ping_submit (host, latency);
        }
-}
+
+       return (0);
+} /* int ping_read */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, ping_init, ping_read, ping_write);
-       cf_register (MODULE_NAME, ping_config, config_keys, config_keys_num);
-}
-
-#undef MODULE_NAME
+       plugin_register_data_set (&ds);
+       plugin_register_init ("ping", ping_init);
+       plugin_register_read ("ping", ping_read);
+       plugin_register_config ("ping", ping_config, config_keys, config_keys_num);
+} /* void module_register */
index d708b6b..f2e205a 100644 (file)
@@ -4,8 +4,7 @@
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 #include <ltdl.h>
 
 #include "plugin.h"
-#include "network.h"
+#include "configfile.h"
+#include "utils_llist.h"
 #include "utils_debug.h"
 
-typedef struct plugin
+/*
+ * Private structures
+ */
+struct read_func_s
 {
-       char *type;
-       void (*init) (void);
-       void (*read) (void);
-       void (*write) (char *host, char *inst, char *val);
-       void (*shutdown) (void);
-       struct plugin *next;
-} plugin_t;
-
-static plugin_t *first_plugin = NULL;
+       int wait_time;
+       int wait_left;
+       int (*callback) (void);
+};
+typedef struct read_func_s read_func_t;
 
-extern int operating_mode;
+/*
+ * Private variables
+ */
+static llist_t *list_init;
+static llist_t *list_read;
+static llist_t *list_write;
+static llist_t *list_shutdown;
+static llist_t *list_data_set;
+static llist_t *list_log;
 
 static char *plugindir = NULL;
 
-char *plugin_get_dir (void)
+/*
+ * Static functions
+ */
+static const char *plugin_get_dir (void)
 {
        if (plugindir == NULL)
                return (PLUGINDIR);
@@ -52,66 +62,52 @@ char *plugin_get_dir (void)
                return (plugindir);
 }
 
-void plugin_set_dir (const char *dir)
+static int register_callback (llist_t **list, const char *name, void *callback)
 {
-       if (plugindir != NULL)
-               free (plugindir);
+       llentry_t *le;
 
-       if (dir == NULL)
-               plugindir = NULL;
-       else if ((plugindir = strdup (dir)) == NULL)
-               syslog (LOG_ERR, "strdup: %s", strerror (errno));
-}
+       if ((*list == NULL)
+                       && ((*list = llist_create ()) == NULL))
+               return (-1);
 
-/*
- * Returns the number of plugins registered
- */
-int plugin_count (void)
-{
-       int i;
-       plugin_t *p;
+       le = llist_search (*list, name);
+       if (le == NULL)
+       {
+               le = llentry_create (name, callback);
+               if (le == NULL)
+                       return (-1);
 
-       for (i = 0, p = first_plugin; p != NULL; p = p->next)
-               i++;
+               llist_append (*list, le);
+       }
+       else
+       {
+               le->value = callback;
+       }
 
-       return (i);
-}
+       return (0);
+} /* int register_callback */
 
-/*
- * Returns the plugins with the type `type' or NULL if it's not found.
- */
-plugin_t *plugin_search (const char *type)
+static int plugin_unregister (llist_t *list, const char *name)
 {
-       plugin_t *ret;
+       llentry_t *e;
 
-       if (type == NULL)
-               return (NULL);
+       e = llist_search (list, name);
 
-       for (ret = first_plugin; ret != NULL; ret = ret->next)
-               if (strcmp (ret->type, type) == 0)
-                       break;
+       if (e == NULL)
+               return (-1);
 
-       return (ret);
-}
+       llist_remove (list, e);
+       llentry_destroy (e);
 
-/*
- * Returns true if the plugin is loaded (i.e. `exists') and false otherwise.
- * This is used in `configfile.c' to skip sections that are not needed..
- */
-int plugin_exists (char *type)
-{
-       if (plugin_search (type) == NULL)
-               return (0);
-       else
-               return (1);
-}
+       return (0);
+} /* int plugin_unregister */
 
 /*
  * (Try to) load the shared object `file'. Won't complain if it isn't a shared
  * object, but it will bitch about a shared object not having a
  * ``module_register'' symbol..
  */
-int plugin_load_file (char *file)
+static int plugin_load_file (char *file)
 {
        lt_dlhandle dlh;
        void (*reg_handle) (void);
@@ -143,11 +139,25 @@ int plugin_load_file (char *file)
        return (0);
 }
 
+/*
+ * Public functions
+ */
+void plugin_set_dir (const char *dir)
+{
+       if (plugindir != NULL)
+               free (plugindir);
+
+       if (dir == NULL)
+               plugindir = NULL;
+       else if ((plugindir = strdup (dir)) == NULL)
+               syslog (LOG_ERR, "strdup failed: %s", strerror (errno));
+}
+
 #define BUFSIZE 512
 int plugin_load (const char *type)
 {
        DIR  *dh;
-       char *dir;
+       const char *dir;
        char  filename[BUFSIZE];
        char  typename[BUFSIZE];
        int   typename_len;
@@ -160,10 +170,6 @@ int plugin_load (const char *type)
        dir = plugin_get_dir ();
        ret = 1;
 
-       /* don't load twice */
-       if (plugin_search (type) != NULL)
-               return (0);
-
        /* `cpu' should not match `cpufreq'. To solve this we add `.so' to the
         * type when matching the filename */
        if (snprintf (typename, BUFSIZE, "%s.so", type) >= BUFSIZE)
@@ -215,184 +221,266 @@ int plugin_load (const char *type)
 }
 
 /*
- * (Try to) load all plugins in `dir'. Returns the number of loaded plugins..
+ * The `register_*' functions follow
  */
-int plugin_load_all (char *dir)
+int plugin_register_config (const char *name,
+               int (*callback) (const char *key, const char *val),
+               const char **keys, int keys_num)
 {
-       DIR *dh;
-       struct dirent *de;
-       char filename[BUFSIZE];
-       struct stat statbuf;
+       cf_register (name, callback, keys, keys_num);
+       return (0);
+} /* int plugin_register_config */
 
-       if (dir == NULL)
-               dir = plugin_get_dir ();
-       else
-               plugin_set_dir (dir);
+int plugin_register_init (const char *name,
+               int (*callback) (void))
+{
+       return (register_callback (&list_init, name, (void *) callback));
+} /* plugin_register_init */
 
-       if ((dh = opendir (dir)) == NULL)
+int plugin_register_read (const char *name,
+               int (*callback) (void))
+{
+       read_func_t *rf;
+
+       rf = (read_func_t *) malloc (sizeof (read_func_t));
+       if (rf == NULL)
        {
-               syslog (LOG_ERR, "opendir (%s): %s", dir, strerror (errno));
-               return (0);
+               syslog (LOG_ERR, "plugin_register_read: malloc failed: %s",
+                               strerror (errno));
+               return (-1);
        }
 
-       while ((de = readdir (dh)) != NULL)
-       {
-               if (snprintf (filename, BUFSIZE, "%s/%s", dir, de->d_name) >= BUFSIZE)
-               {
-                       syslog (LOG_WARNING, "snprintf: truncated: %s/%s", dir, de->d_name);
-                       continue;
-               }
+       memset (rf, '\0', sizeof (read_func_t));
+       rf->wait_time = atoi (COLLECTD_STEP);
+       rf->wait_left = 0;
+       rf->callback = callback;
 
-               if (lstat (filename, &statbuf) == -1)
-               {
-                       syslog (LOG_WARNING, "stat %s: %s", filename, strerror (errno));
-                       continue;
-               }
-               else if (!S_ISREG (statbuf.st_mode))
-               {
-                       continue;
-               }
+       return (register_callback (&list_read, name, (void *) rf));
+} /* int plugin_register_read */
 
-               plugin_load_file (filename);
-       }
+int plugin_register_write (const char *name,
+               int (*callback) (const data_set_t *ds, const value_list_t *vl))
+{
+       return (register_callback (&list_write, name, (void *) callback));
+} /* int plugin_register_write */
 
-       closedir (dh);
+int plugin_register_shutdown (char *name,
+               int (*callback) (void))
+{
+       return (register_callback (&list_shutdown, name, (void *) callback));
+} /* int plugin_register_shutdown */
 
-       return (plugin_count ());
-}
-#undef BUFSIZE
+int plugin_register_data_set (const data_set_t *ds)
+{
+       return (register_callback (&list_data_set, ds->type, (void *) ds));
+} /* int plugin_register_data_set */
 
-/*
- * Call `init' on all plugins (if given)
- */
-void plugin_init_all (void)
+int plugin_register_log (char *name,
+               void (*callback) (int priority, const char *msg))
 {
-       plugin_t *p;
+       return (register_callback (&list_log, name, (void *) callback));
+} /* int plugin_register_log */
 
-       for (p = first_plugin; p != NULL; p = p->next)
-               if (p->init != NULL)
-                       (*p->init) ();
+int plugin_unregister_init (const char *name)
+{
+       return (plugin_unregister (list_init, name));
 }
 
-/*
- * Call `read' on all plugins (if given)
- */
-void plugin_read_all (const int *loop)
+int plugin_unregister_read (const char *name)
 {
-       plugin_t *p;
+       return (plugin_unregister (list_read, name));
+       llentry_t *e;
 
-       for (p = first_plugin; (*loop == 0) && (p != NULL); p = p->next)
-               if (p->read != NULL)
-                       (*p->read) ();
+       e = llist_search (list_read, name);
+
+       if (e == NULL)
+               return (-1);
+
+       llist_remove (list_read, e);
+       free (e->value);
+       llentry_destroy (e);
+
+       return (0);
 }
 
-/*
- * Call `shutdown' on all plugins (if given)
- */
-void plugin_shutdown_all (void)
+int plugin_unregister_write (const char *name)
 {
-       plugin_t *p;
+       return (plugin_unregister (list_write, name));
+}
 
-       for (p = first_plugin; NULL != p; p = p->next)
-               if (NULL != p->shutdown)
-                       (*p->shutdown) ();
-       return;
+int plugin_unregister_shutdown (const char *name)
+{
+       return (plugin_unregister (list_shutdown, name));
 }
 
-/*
- * Add plugin to the linked list of registered plugins.
- */
-void plugin_register (char *type,
-               void (*init) (void),
-               void (*read) (void),
-               void (*write) (char *, char *, char *))
+int plugin_unregister_data_set (const char *name)
 {
-       plugin_t *p;
+       return (plugin_unregister (list_data_set, name));
+}
 
-       if (plugin_search (type) != NULL)
-               return;
+int plugin_unregister_log (const char *name)
+{
+       return (plugin_unregister (list_log, name));
+}
 
-#ifdef HAVE_LIBRRD
-       if (operating_mode != MODE_SERVER)
-#endif
-               if ((init != NULL) && (read == NULL))
-                       syslog (LOG_NOTICE, "Plugin `%s' doesn't provide a read function.", type);
+void plugin_init_all (void)
+{
+       int (*callback) (void);
+       llentry_t *le;
+       int status;
 
-       if ((p = (plugin_t *) malloc (sizeof (plugin_t))) == NULL)
+       if (list_init == NULL)
                return;
 
-       if ((p->type = strdup (type)) == NULL)
+       le = llist_head (list_init);
+       while (le != NULL)
        {
-               free (p);
-               return;
+               callback = le->value;
+               status = (*callback) ();
+
+               if (status != 0)
+               {
+                       syslog (LOG_ERR, "Initialization of plugin `%s' "
+                                       "failed with status %i. "
+                                       "Plugin will be unloaded. TODO!",
+                                       le->key, status);
+                       plugin_unregister_read (le->key);
+               }
+
+               le = le->next;
        }
+} /* void plugin_init_all */
 
-       p->init  = init;
-       p->read  = read;
-       p->write = write;
+void plugin_read_all (const int *loop)
+{
+       llentry_t   *le;
+       read_func_t *rf;
+       int          status;
+       int          step;
 
-       p->shutdown = NULL;
+       if (list_read == NULL)
+               return;
 
-       p->next = first_plugin;
-       first_plugin = p;
-}
+       step = atoi (COLLECTD_STEP);
 
-/*
- * Register the shutdown function (optional).
- */
-int plugin_register_shutdown (char *type, void (*shutdown) (void))
-{
-       plugin_t *p = plugin_search (type);
+       le = llist_head (list_read);
+       while ((*loop == 0) && (le != NULL))
+       {
+               rf = (read_func_t *) le->value;
 
-       if (NULL == p)
-               return -1;
+               if (rf->wait_left > 0)
+                       rf->wait_left -= step;
+               if (rf->wait_left > 0)
+               {
+                       le = le->next;
+                       continue;
+               }
 
-       p->shutdown = shutdown;
-       return 0;
-}
+               status = rf->callback ();
+               if (status != 0)
+               {
+                       rf->wait_left = rf->wait_time;
+                       rf->wait_time = rf->wait_time * 2;
+                       if (rf->wait_time > 86400)
+                               rf->wait_time = 86400;
+
+                       syslog (LOG_NOTICE, "read-function of plugin `%s' "
+                                       "failed. Will syspend it for %i "
+                                       "seconds.", le->key, rf->wait_left);
+               }
+               else
+               {
+                       rf->wait_left = 0;
+                       rf->wait_time = step;
+               }
 
-/*
- * Send received data back to the plugin/module which will append DS
- * definitions and pass it on to ``rrd_update_file''.
- */
-void plugin_write (char *host, char *type, char *inst, char *val)
+               le = le->next;
+       } /* while ((*loop == 0) && (le != NULL)) */
+} /* void plugin_read_all */
+
+void plugin_shutdown_all (void)
 {
-       plugin_t *p;
+       int (*callback) (void);
+       llentry_t *le;
 
-       if ((p = plugin_search (type)) == NULL)
+       if (list_shutdown == NULL)
                return;
 
-       if (p->write == NULL)
-               return;
+       le = llist_head (list_shutdown);
+       while (le != NULL)
+       {
+               callback = le->value;
+               (*callback) ();
 
-       (*p->write) (host, inst, val);
-}
+               le = le->next;
+       }
+} /* void plugin_shutdown_all */
 
-/*
- * Receive data from the plugin/module and get it somehow to ``plugin_write'':
- * Either using ``network_send'' (when in network/client mode) or call it
- * directly (in local mode).
- */
-void plugin_submit (char *type, char *inst, char *val)
+int plugin_dispatch_values (const char *name, const value_list_t *vl)
 {
-       if (inst == NULL)
-               inst = "-";
+       int (*callback) (const data_set_t *, const value_list_t *);
+       data_set_t *ds;
+       llentry_t *le;
+
+       if (list_write == NULL)
+               return (-1);
 
-       if ((type == NULL) || (val == NULL))
+       le = llist_search (list_data_set, name);
+       if (le == NULL)
        {
-               DBG ("Help! NULL-pointer! type = %s; inst = %s; val = %s;",
-                               (type == NULL) ? "(null)" : type,
-                               inst,
-                               (val == NULL) ? "(null)" : val);
-               return;
+               DBG ("No such dataset registered: %s", name);
+               return (-1);
        }
 
-        if (operating_mode == MODE_CLIENT)
-               network_send (type, inst, val);
-       else
-               plugin_write (NULL, type, inst, val);
+       ds = (data_set_t *) le->value;
+
+       DBG ("time = %u; host = %s; "
+                       "plugin = %s; plugin_instance = %s; "
+                       "type = %s; type_instance = %s;",
+                       (unsigned int) vl->time, vl->host,
+                       vl->plugin, vl->plugin_instance,
+                       ds->type, vl->type_instance);
+
+       le = llist_head (list_write);
+       while (le != NULL)
+       {
+               callback = le->value;
+               (*callback) (ds, vl);
+
+               le = le->next;
+       }
+
+       return (0);
 }
 
+void plugin_log (int level, const char *format, ...)
+{
+       char msg[512];
+       va_list ap;
+
+       void (*callback) (int, const char *);
+       llentry_t *le;
+
+#if !COLLECT_DEBUG
+       if (level >= LOG_DEBUG)
+               return;
+#endif
+
+       va_start (ap, format);
+       vsnprintf (msg, 512, format, ap);
+       msg[511] = '\0';
+       va_end (ap);
+
+       le = llist_head (list_log);
+       while (le != NULL)
+       {
+               callback = le->value;
+               (*callback) (level, msg);
+
+               le = le->next;
+       }
+} /* void plugin_log */
+
 void plugin_complain (int level, complain_t *c, const char *format, ...)
 {
        char message[512];
index 45e9b49..cf2c3f7 100644 (file)
@@ -7,8 +7,7 @@
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  *   Florian octo Forster <octo at verplant.org>
  **/
 
+#define DATA_MAX_NAME_LEN 64
+
+#define DS_TYPE_COUNTER 0
+#define DS_TYPE_GAUGE   1
+
+#ifndef LOG_ERR
+# define LOG_ERR 3
+#endif
+#ifndef LOG_WARNING
+# define LOG_WARNING 4
+#endif
+#ifndef LOG_NOTICE
+# define LOG_NOTICE 5
+#endif
+#ifndef LOG_INFO
+# define LOG_INFO 6
+#endif
+#ifndef LOG_DEBUG
+# define LOG_DEBUG 7
+#endif
+
 /*
- *
+ * Public data types
  */
+typedef unsigned long long counter_t;
+typedef double gauge_t;
+
+union value_u
+{
+       counter_t counter;
+       gauge_t   gauge;
+};
+typedef union value_u value_t;
+
+struct value_list_s
+{
+       value_t *values;
+       int      values_len;
+       time_t   time;
+       char     host[DATA_MAX_NAME_LEN];
+       char     plugin[DATA_MAX_NAME_LEN];
+       char     plugin_instance[DATA_MAX_NAME_LEN];
+       char     type_instance[DATA_MAX_NAME_LEN];
+};
+typedef struct value_list_s value_list_t;
+
+#define VALUE_LIST_INIT { NULL, 0, 0, "localhost", "", "", "" }
+
+struct data_source_s
+{
+       char   name[DATA_MAX_NAME_LEN];
+       int    type;
+       double min;
+       double max;
+};
+typedef struct data_source_s data_source_t;
+
+struct data_set_s
+{
+       char           type[DATA_MAX_NAME_LEN];
+       int            ds_num;
+       data_source_t *ds;
+};
+typedef struct data_set_s data_set_t;
+
 typedef struct complain_s
 {
        unsigned int interval; /* how long we wait for reporting this error again */
@@ -49,34 +110,6 @@ void plugin_set_dir (const char *dir);
 
 /*
  * NAME
- *  plugin_count
- *
- * DESCRIPTION
- *  trivial
- *
- * RETURN VALUE
- *  The number of currently loaded plugins
- */
-int plugin_count (void);
-
-/*
- * NAME
- *  plugin_exists
- *
- * DESCRIPTION
- *  trivial
- *
- * ARGUMENTS
- *  `type'      Name of the plugin.
- *
- * RETURN VALUE
- *  Returns non-zero if a plugin with the name $type is found and zero
- *  otherwise.
- */
-int plugin_exists (char *type);
-
-/*
- * NAME
  *  plugin_load
  *
  * DESCRIPTION
@@ -95,42 +128,64 @@ int plugin_exists (char *type);
  * NOTES
  *  No attempt is made to re-load an already loaded module.
  */
-int  plugin_load (const char *type);
+int  plugin_load (const char *name);
 
-int  plugin_load_all (char *dir);
 void plugin_init_all (void);
 void plugin_read_all (const int *loop);
-
 void plugin_shutdown_all (void);
 
-void plugin_register (char *type,
-               void (*init) (void),
-               void (*read) (void),
-               void (*write) (char *, char *, char *));
+/*
+ * The `plugin_register_*' functions are used to make `config', `init',
+ * `read', `write' and `shutdown' functions known to the plugin
+ * infrastructure. Also, the data-formats are made public like this.
+ */
+int plugin_register_config (const char *name,
+               int (*callback) (const char *key, const char *val),
+               const char **keys, int keys_num);
+int plugin_register_init (const char *name,
+               int (*callback) (void));
+int plugin_register_read (const char *name,
+               int (*callback) (void));
+int plugin_register_write (const char *name,
+               int (*callback) (const data_set_t *ds, const value_list_t *vl));
+int plugin_register_shutdown (char *name,
+               int (*callback) (void));
+int plugin_register_data_set (const data_set_t *ds);
+int plugin_register_log (char *name,
+               void (*callback) (int, const char *));
 
-int plugin_register_shutdown (char *, void (*) (void));
+int plugin_unregister_init (const char *name);
+int plugin_unregister_read (const char *name);
+int plugin_unregister_write (const char *name);
+int plugin_unregister_shutdown (const char *name);
+int plugin_unregister_data_set (const char *name);
+int plugin_unregister_log (const char *name);
 
 /*
  * NAME
- *  plugin_write
+ *  plugin_dispatch_values
  *
  * DESCRIPTION
- *  Searches the plugin for `type' in the plugin-list. If found, and a `write'
- *  function is registered, it's called. If either the plugin is not found or
- *  the plugin doesn't provide a `write' function this function will return
- *  without further notice.
+ *  This function is called by reading processes with the values they've
+ *  aquired. The function fetches the data-set definition (that has been
+ *  registered using `plugin_register_data_set') and calls _all_ registered
+ *  write-functions.
  *
  * ARGUMENTS
- *  `host'      Host(name) from which the data originates.
- *  `type'      Name of the plugin.
- *  `inst'      Instance (passed to the plugin's `write' function.
- *  `val'       Values for the RRD files. Also passed to the plugin.
+ *  `name'      Name/type of the data-set that describe the values in `vl'.
+ *  `vl'        Value list of the values that have been read by a `read'
+ *              function.
  */
-void plugin_write    (char *host, char *type, char *inst, char *val);
-
-void plugin_submit   (char *type, char *inst, char *val);
+int plugin_dispatch_values (const char *name, const value_list_t *vl);
 
+void plugin_log (int level, const char *format, ...);
+#define ERROR(...)   plugin_log (LOG_ERR,     __VA_ARGS__)
+#define WARNING(...) plugin_log (LOG_WARNING, __VA_ARGS__)
+#define NOTICE(...)  plugin_log (LOG_NOTICE,  __VA_ARGS__)
+#define INFO(...)    plugin_log (LOG_INFO,    __VA_ARGS__)
+#define DEBUG(...)   plugin_log (LOG_DEBUG,   __VA_ARGS__)
 
+/* TODO: Move plugin_{complain,relief} into `utils_complain.[ch]'. -octo */
 void plugin_complain (int level, complain_t *c, const char *format, ...);
 void plugin_relief (int level, complain_t *c, const char *format, ...);
 
index 6898445..37d0a75 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * collectd - src/processes.c
  * Copyright (C) 2005  Lyonel Vincent
- * Copyright (C) 2006  Florian Forster (Mach code)
+ * Copyright (C) 2006-2007  Florian Forster (Mach code)
  *
  * 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
 
 #define BUFSIZE 256
 
-static char *processes_file = "processes.rrd";
-static char *processes_ds_def[] =
+static data_source_t state_dsrc[1] =
 {
-       "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       "DS:sleeping:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       "DS:zombies:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       "DS:stopped:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       "DS:paging:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       "DS:blocked:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       NULL
+       {"value", DS_TYPE_GAUGE, 0.0, 65535.0}
 };
-static int processes_ds_num = 6;
 
-static char *ps_rss_file = "processes/ps_rss-%s.rrd";
-static char *ps_rss_ds_def[] =
+static data_set_t state_ds =
+{
+       "ps_state", 1, state_dsrc
+};
+
+static data_source_t rss_dsrc[1] =
 {
        /* max = 2^63 - 1 */
-       "DS:byte:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       NULL
+       {"value", DS_TYPE_GAUGE, 0.0, 9223372036854775807.0}
 };
-static int ps_rss_ds_num = 1;
 
-static char *ps_cputime_file = "processes/ps_cputime-%s.rrd";
-static char *ps_cputime_ds_def[] =
+static data_set_t rss_ds =
+{
+       "ps_rss", 1, rss_dsrc
+};
+
+static data_source_t time_dsrc[2] =
 {
        /* 1 second in user-mode per second ought to be enough.. */
-       "DS:user:COUNTER:"COLLECTD_HEARTBEAT":0:1000000",
-       "DS:syst:COUNTER:"COLLECTD_HEARTBEAT":0:1000000",
-       NULL
+       {"user", DS_TYPE_COUNTER, 0.0, 1000000.0},
+       {"syst", DS_TYPE_COUNTER, 0.0, 1000000.0}
 };
-static int ps_cputime_ds_num = 2;
 
-static char *ps_count_file = "processes/ps_count-%s.rrd";
-static char *ps_count_ds_def[] =
+static data_set_t time_ds =
 {
-       "DS:processes:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       "DS:threads:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       NULL
+       "ps_cputime", 2, time_dsrc
+};
+
+static data_source_t count_dsrc[2] =
+{
+       /* 1 second in user-mode per second ought to be enough.. */
+       {"processes", DS_TYPE_GAUGE, 0.0, 1000000.0},
+       {"threads",   DS_TYPE_GAUGE, 0.0, 1000000.0}
 };
-static int ps_count_ds_num = 2;
 
-static char *ps_pagefaults_file = "processes/ps_pagefaults-%s.rrd";
-static char *ps_pagefaults_ds_def[] =
+static data_set_t count_ds =
+{
+       "ps_count", 2, count_dsrc
+};
+
+static data_source_t pagefaults_dsrc[2] =
 {
        /* max = 2^63 - 1 */
-       "DS:minflt:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:majflt:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       NULL
+       {"minflt", DS_TYPE_COUNTER, 0.0, 9223372036854775807.0},
+       {"majflt", DS_TYPE_COUNTER, 0.0, 9223372036854775807.0}
 };
-static int ps_pagefaults_ds_num = 2;
 
+static data_set_t pagefaults_ds =
+{
+       "ps_pagefaults", 2, pagefaults_dsrc
+};
+
+#if PROCESSES_HAVE_READ
 #if HAVE_THREAD_INFO | KERNEL_LINUX
-static char *config_keys[] =
+static const char *config_keys[] =
 {
        "Process",
        NULL
@@ -408,7 +415,7 @@ static void ps_list_reset (void)
        } /* for (ps = list_head_g; ps != NULL; ps = ps->next) */
 }
 
-static int ps_config (char *key, char *value)
+static int ps_config (const char *key, const char *value)
 {
        if (strcasecmp (key, "Process") == 0)
        {
@@ -423,7 +430,7 @@ static int ps_config (char *key, char *value)
 }
 #endif /* HAVE_THREAD_INFO | KERNEL_LINUX */
 
-static void ps_init (void)
+static int ps_init (void)
 {
 #if HAVE_THREAD_INFO
        kern_return_t status;
@@ -448,7 +455,7 @@ static void ps_init (void)
                                mach_error_string (status));
                pset_list = NULL;
                pset_list_len = 0;
-               return;
+               return (-1);
        }
 /* #endif HAVE_THREAD_INFO */
 
@@ -458,135 +465,65 @@ static void ps_init (void)
                        pagesize_g, CONFIG_HZ);
 #endif /* KERNEL_LINUX */
 
-       return;
-}
-
-static void ps_write (char *host, char *inst, char *val)
-{
-       rrd_update_file (host, processes_file, val,
-                       processes_ds_def, processes_ds_num);
-}
-
-static void ps_rss_write (char *host, char *inst, char *val)
-{
-       char filename[256];
-       int status;
-
-       status = snprintf (filename, 256, ps_rss_file, inst);
-       if ((status < 1) || (status >= 256))
-               return;
-
-       rrd_update_file (host, filename, val, ps_rss_ds_def, ps_rss_ds_num);
-}
-
-static void ps_cputime_write (char *host, char *inst, char *val)
-{
-       char filename[256];
-       int status;
-
-       status = snprintf (filename, 256, ps_cputime_file, inst);
-       if ((status < 1) || (status >= 256))
-               return;
-
-       DBG ("host = %s; filename = %s; val = %s;",
-                       host, filename, val);
-       rrd_update_file (host, filename, val,
-                       ps_cputime_ds_def, ps_cputime_ds_num);
-}
-
-static void ps_count_write (char *host, char *inst, char *val)
-{
-       char filename[256];
-       int status;
-
-       status = snprintf (filename, 256, ps_count_file, inst);
-       if ((status < 1) || (status >= 256))
-               return;
-
-       DBG ("host = %s; filename = %s; val = %s;",
-                       host, filename, val);
-       rrd_update_file (host, filename, val,
-                       ps_count_ds_def, ps_count_ds_num);
-}
-
-static void ps_pagefaults_write (char *host, char *inst, char *val)
-{
-       char filename[256];
-       int status;
-
-       status = snprintf (filename, 256, ps_pagefaults_file, inst);
-       if ((status < 1) || (status >= 256))
-               return;
-
-       DBG ("host = %s; filename = %s; val = %s;",
-                       host, filename, val);
-       rrd_update_file (host, filename, val,
-                       ps_pagefaults_ds_def, ps_pagefaults_ds_num);
-}
+       return (0);
+} /* int ps_init */
 
-#if PROCESSES_HAVE_READ
-static void ps_submit (int running,
-               int sleeping,
-               int zombies,
-               int stopped,
-               int paging,
-               int blocked)
+static void ps_submit_state (const char *state, double value)
 {
-       char buf[BUFSIZE];
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       if (snprintf (buf, BUFSIZE, "%u:%i:%i:%i:%i:%i:%i",
-                               (unsigned int) curtime,
-                               running, sleeping, zombies, stopped, paging,
-                               blocked) >= BUFSIZE)
-               return;
+       values[0].gauge = value;
 
-       DBG ("running = %i; sleeping = %i; zombies = %i; stopped = %i; paging = %i; blocked = %i;",
-                       running, sleeping, zombies, stopped, paging, blocked);
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "processes");
+       strcpy (vl.plugin_instance, "");
+       strncpy (vl.type_instance, state, sizeof (vl.type_instance));
 
-       plugin_submit (MODULE_NAME, "-", buf);
+       plugin_dispatch_values ("ps_state", &vl);
 }
 
 static void ps_submit_proc_list (procstat_t *ps)
 {
-       char buffer[64];
-
-       if (ps == NULL)
-               return;
-
-       snprintf (buffer, 64, "%u:%lu",
-                       (unsigned int) curtime,
-                       ps->vmem_rss);
-       buffer[63] = '\0';
-       plugin_submit ("ps_rss", ps->name, buffer);
-
-       snprintf (buffer, 64, "%u:%u:%u",
-                       (unsigned int) curtime,
-                       /* Make the counter overflow */
-                       (unsigned int) (ps->cpu_user_counter   & 0xFFFFFFFF),
-                       (unsigned int) (ps->cpu_system_counter & 0xFFFFFFFF));
-       buffer[63] = '\0';
-       plugin_submit ("ps_cputime", ps->name, buffer);
-
-       snprintf (buffer, 64, "%u:%lu:%lu",
-                       (unsigned int) curtime,
-                       ps->num_proc, ps->num_lwp);
-       buffer[63] = '\0';
-       plugin_submit ("ps_count", ps->name, buffer);
-
-       snprintf (buffer, 64, "%u:%lu:%lu",
-                       (unsigned int) curtime,
-                       ps->vmem_minflt_counter, ps->vmem_majflt_counter);
-       buffer[63] = '\0';
-       plugin_submit ("ps_pagefaults", ps->name, buffer);
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values = values;
+       vl.values_len = 2;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "processes");
+       strncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance));
+
+       vl.values[0].gauge = ps->vmem_rss;
+       vl.values_len = 1;
+       plugin_dispatch_values ("ps_rss", &vl);
+
+       vl.values[0].counter = ps->cpu_user_counter;
+       vl.values[1].counter = ps->cpu_system_counter;
+       vl.values_len = 2;
+       plugin_dispatch_values ("ps_cputime", &vl);
+
+       vl.values[0].gauge = ps->num_proc;
+       vl.values[1].gauge = ps->num_lwp;
+       vl.values_len = 2;
+       plugin_dispatch_values ("ps_count", &vl);
+
+       vl.values[0].counter = ps->vmem_minflt_counter;
+       vl.values[1].counter = ps->vmem_majflt_counter;
+       vl.values_len = 2;
+       plugin_dispatch_values ("ps_pagefaults", &vl);
 
        DBG ("name = %s; num_proc = %lu; num_lwp = %lu; vmem_rss = %lu; "
                        "vmem_minflt_counter = %lu; vmem_majflt_counter = %lu; "
                        "cpu_user_counter = %lu; cpu_system_counter = %lu;",
                        ps->name, ps->num_proc, ps->num_lwp, ps->vmem_rss,
-                       ps->vmem_minflt_counter, ps->vmem_majflt_counter, ps->cpu_user_counter,
-                       ps->cpu_system_counter);
-
-}
+                       ps->vmem_minflt_counter, ps->vmem_majflt_counter,
+                       ps->cpu_user_counter, ps->cpu_system_counter);
+} /* void ps_submit_proc_list */
 
 #if KERNEL_LINUX
 static int *ps_read_tasks (int pid)
@@ -794,7 +731,7 @@ static int mach_get_task_name (task_t t, int *pid, char *name, size_t name_max_l
 }
 #endif /* HAVE_THREAD_INFO */
 
-static void ps_read (void)
+static int ps_read (void)
 {
 #if HAVE_THREAD_INFO
        kern_return_t            status;
@@ -1041,7 +978,11 @@ static void ps_read (void)
                }
        } /* for (pset_list) */
 
-       ps_submit (running, sleeping, zombies, stopped, -1, blocked);
+       ps_submit_state ("running", running);
+       ps_submit_state ("sleeping", sleeping);
+       ps_submit_state ("zombies", zombies);
+       ps_submit_state ("stopped", stopped);
+       ps_submit_state ("blocked", blocked);
 
        for (ps = list_head_g; ps != NULL; ps = ps->next)
                ps_submit_proc_list (ps);
@@ -1072,7 +1013,7 @@ static void ps_read (void)
        if ((proc = opendir ("/proc")) == NULL)
        {
                syslog (LOG_ERR, "Cannot open `/proc': %s", strerror (errno));
-               return;
+               return (-1);
        }
 
        while ((ent = readdir (proc)) != NULL)
@@ -1122,27 +1063,36 @@ static void ps_read (void)
 
        closedir (proc);
 
-       ps_submit (running, sleeping, zombies, stopped, paging, blocked);
+       ps_submit_state ("running",  running);
+       ps_submit_state ("sleeping", sleeping);
+       ps_submit_state ("zombies",  zombies);
+       ps_submit_state ("stopped",  stopped);
+       ps_submit_state ("paging",   paging);
+       ps_submit_state ("blocked",  blocked);
 
        for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
                ps_submit_proc_list (ps_ptr);
 #endif /* KERNEL_LINUX */
-}
-#else
-# define ps_read NULL
+
+       return (0);
+} /* int ps_read */
 #endif /* PROCESSES_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, ps_init, ps_read, ps_write);
-       plugin_register ("ps_rss", NULL, NULL, ps_rss_write);
-       plugin_register ("ps_cputime", NULL, NULL, ps_cputime_write);
-       plugin_register ("ps_count", NULL, NULL, ps_count_write);
-       plugin_register ("ps_pagefaults", NULL, NULL, ps_pagefaults_write);
+       plugin_register_data_set (&state_ds);
+       plugin_register_data_set (&rss_ds);
+       plugin_register_data_set (&time_ds);
+       plugin_register_data_set (&count_ds );
+       plugin_register_data_set (&pagefaults_ds );
+
+#if PROCESSES_HAVE_READ
 #if HAVE_THREAD_INFO | KERNEL_LINUX
-       cf_register (MODULE_NAME, ps_config, config_keys, config_keys_num);
+       plugin_register_config ("processes", ps_config,
+                       config_keys, config_keys_num);
 #endif
+       plugin_register_init ("processes", ps_init);
+       plugin_register_read ("processes", ps_read);
+#endif /* PROCESSES_HAVE_READ */
 }
 
-#undef BUFSIZE
-#undef MODULE_NAME
diff --git a/src/rrdtool.c b/src/rrdtool.c
new file mode 100644 (file)
index 0000000..f19f269
--- /dev/null
@@ -0,0 +1,802 @@
+/**
+ * collectd - src/rrdtool.c
+ * Copyright (C) 2006  Florian octo Forster
+ *
+ * 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; only version 2 of the License is applicable.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_avltree.h"
+#include "utils_debug.h"
+
+/*
+ * Private types
+ */
+struct rrd_cache_s
+{
+       int    values_num;
+       char **values;
+       time_t first_value;
+};
+typedef struct rrd_cache_s rrd_cache_t;
+
+/*
+ * Private variables
+ */
+static int rra_timespans[] =
+{
+       3600,
+       86400,
+       604800,
+       2678400,
+       31622400
+};
+static int rra_timespans_num = STATIC_ARRAY_SIZE (rra_timespans);
+
+static char *rra_types[] =
+{
+       "AVERAGE",
+       "MIN",
+       "MAX"
+};
+static int rra_types_num = STATIC_ARRAY_SIZE (rra_types);
+
+static const char *config_keys[] =
+{
+       "CacheTimeout",
+       "CacheFlush",
+       "DataDir",
+       "StepSize",
+       "HeartBeat",
+       "RRARows",
+       "XFF"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static char   *datadir   = NULL;
+static int     stepsize  = 0;
+static int     heartbeat = 0;
+static int     rrarows   = 1200;
+static double  xff       = 0.1;
+
+static int         cache_timeout = 0;
+static int         cache_flush_timeout = 0;
+static time_t      cache_flush_last;
+static avl_tree_t *cache = NULL;
+
+/* * * * * * * * * *
+ * WARNING:  Magic *
+ * * * * * * * * * */
+static int rra_get (char ***ret)
+{
+       static char **rra_def = NULL;
+       static int rra_num = 0;
+
+       int rra_max = rra_timespans_num * rra_types_num;
+
+       int span;
+
+       int cdp_num;
+       int cdp_len;
+       int i, j;
+
+       char buffer[64];
+
+       if ((rra_num != 0) && (rra_def != NULL))
+       {
+               *ret = rra_def;
+               return (rra_num);
+       }
+
+       if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
+               return (-1);
+       memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
+
+       if ((stepsize <= 0) || (rrarows <= 0))
+       {
+               *ret = NULL;
+               return (-1);
+       }
+
+       cdp_len = 0;
+       for (i = 0; i < rra_timespans_num; i++)
+       {
+               span = rra_timespans[i];
+
+               if ((span / stepsize) < rrarows)
+                       continue;
+
+               if (cdp_len == 0)
+                       cdp_len = 1;
+               else
+                       cdp_len = (int) floor (((double) span)
+                                       / ((double) (rrarows * stepsize)));
+
+               cdp_num = (int) ceil (((double) span)
+                               / ((double) (cdp_len * stepsize)));
+
+               for (j = 0; j < rra_types_num; j++)
+               {
+                       if (rra_num >= rra_max)
+                               break;
+
+                       if (snprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
+                                               rra_types[j], xff,
+                                               cdp_len, cdp_num) >= sizeof (buffer))
+                       {
+                               syslog (LOG_ERR, "rra_get: Buffer would have been truncated.");
+                               continue;
+                       }
+
+                       rra_def[rra_num++] = sstrdup (buffer);
+               }
+       }
+
+#if COLLECT_DEBUG
+       DBG ("rra_num = %i", rra_num);
+       for (i = 0; i < rra_num; i++)
+               DBG ("  %s", rra_def[i]);
+#endif
+
+       *ret = rra_def;
+       return (rra_num);
+}
+
+static void ds_free (int ds_num, char **ds_def)
+{
+       int i;
+
+       for (i = 0; i < ds_num; i++)
+               if (ds_def[i] != NULL)
+                       free (ds_def[i]);
+       free (ds_def);
+}
+
+static int ds_get (char ***ret, const data_set_t *ds)
+{
+       char **ds_def;
+       int ds_num;
+
+       char min[32];
+       char max[32];
+       char buffer[128];
+
+       DBG ("ds->ds_num = %i", ds->ds_num);
+
+       ds_def = (char **) malloc (ds->ds_num * sizeof (char *));
+       if (ds_def == NULL)
+       {
+               syslog (LOG_ERR, "rrdtool plugin: malloc failed: %s",
+                               strerror (errno));
+               return (-1);
+       }
+       memset (ds_def, '\0', ds->ds_num * sizeof (char *));
+
+       for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
+       {
+               data_source_t *d = ds->ds + ds_num;
+               char *type;
+               int status;
+
+               ds_def[ds_num] = NULL;
+
+               if (d->type == DS_TYPE_COUNTER)
+                       type = "COUNTER";
+               else if (d->type == DS_TYPE_GAUGE)
+                       type = "GAUGE";
+               else
+               {
+                       syslog (LOG_ERR, "rrdtool plugin: Unknown DS type: %i",
+                                       d->type);
+                       break;
+               }
+
+               if (isnan (d->min))
+               {
+                       strcpy (min, "U");
+               }
+               else
+               {
+                       snprintf (min, sizeof (min), "%lf", d->min);
+                       min[sizeof (min) - 1] = '\0';
+               }
+
+               if (isnan (d->max))
+               {
+                       strcpy (max, "U");
+               }
+               else
+               {
+                       snprintf (max, sizeof (max), "%lf", d->max);
+                       max[sizeof (max) - 1] = '\0';
+               }
+
+               status = snprintf (buffer, sizeof (buffer),
+                               "DS:%s:%s:%i:%s:%s",
+                               d->name, type, heartbeat,
+                               min, max);
+               if ((status < 1) || (status >= sizeof (buffer)))
+                       break;
+
+               ds_def[ds_num] = sstrdup (buffer);
+       } /* for ds_num = 0 .. ds->ds_num */
+
+#if COLLECT_DEBUG
+{
+       int i;
+       DBG ("ds_num = %i", ds_num);
+       for (i = 0; i < ds_num; i++)
+               DBG ("  %s", ds_def[i]);
+}
+#endif
+
+       if (ds_num != ds->ds_num)
+       {
+               ds_free (ds_num, ds_def);
+               return (-1);
+       }
+
+       *ret = ds_def;
+       return (ds_num);
+}
+
+static int rrd_create_file (char *filename, const data_set_t *ds)
+{
+       char **argv;
+       int argc;
+       char **rra_def;
+       int rra_num;
+       char **ds_def;
+       int ds_num;
+       int i, j;
+       char stepsize_str[16];
+       int status = 0;
+
+       if (check_create_dir (filename))
+               return (-1);
+
+       if ((rra_num = rra_get (&rra_def)) < 1)
+       {
+               syslog (LOG_ERR, "rrd_create_file failed: Could not calculate RRAs");
+               return (-1);
+       }
+
+       if ((ds_num = ds_get (&ds_def, ds)) < 1)
+       {
+               syslog (LOG_ERR, "rrd_create_file failed: Could not calculate DSes");
+               return (-1);
+       }
+
+       argc = ds_num + rra_num + 4;
+
+       if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
+       {
+               syslog (LOG_ERR, "rrd_create failed: %s", strerror (errno));
+               return (-1);
+       }
+
+       status = snprintf (stepsize_str, sizeof (stepsize_str),
+                       "%i", stepsize);
+       if ((status < 1) || (status >= sizeof (stepsize_str)))
+       {
+               syslog (LOG_ERR, "rrdtool plugin: snprintf failed.");
+               return (-1);
+       }
+
+       argv[0] = "create";
+       argv[1] = filename;
+       argv[2] = "-s";
+       argv[3] = stepsize_str;
+
+       j = 4;
+       for (i = 0; i < ds_num; i++)
+               argv[j++] = ds_def[i];
+       for (i = 0; i < rra_num; i++)
+               argv[j++] = rra_def[i];
+       argv[j] = NULL;
+
+       optind = 0; /* bug in librrd? */
+       rrd_clear_error ();
+       if (rrd_create (argc, argv) == -1)
+       {
+               syslog (LOG_ERR, "rrd_create failed: %s: %s", filename, rrd_get_error ());
+               status = -1;
+       }
+
+       free (argv);
+       ds_free (ds_num, ds_def);
+
+       return (status);
+}
+
+static int value_list_to_string (char *buffer, int buffer_len,
+               const data_set_t *ds, const value_list_t *vl)
+{
+       int offset;
+       int status;
+       int i;
+
+       memset (buffer, '\0', sizeof (buffer_len));
+
+       status = snprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
+       if ((status < 1) || (status >= buffer_len))
+               return (-1);
+       offset = status;
+
+       for (i = 0; i < ds->ds_num; i++)
+       {
+               if ((ds->ds[i].type != DS_TYPE_COUNTER)
+                               && (ds->ds[i].type != DS_TYPE_GAUGE))
+                       return (-1);
+
+               if (ds->ds[i].type == DS_TYPE_COUNTER)
+                       status = snprintf (buffer + offset, buffer_len - offset,
+                                       ":%llu", vl->values[i].counter);
+               else
+                       status = snprintf (buffer + offset, buffer_len - offset,
+                                       ":%lf", vl->values[i].gauge);
+
+               if ((status < 1) || (status >= (buffer_len - offset)))
+                       return (-1);
+
+               offset += status;
+       } /* for ds->ds_num */
+
+       return (0);
+} /* int value_list_to_string */
+
+static int value_list_to_filename (char *buffer, int buffer_len,
+               const data_set_t *ds, const value_list_t *vl)
+{
+       int offset = 0;
+       int status;
+
+       if (datadir != NULL)
+       {
+               status = snprintf (buffer + offset, buffer_len - offset,
+                               "%s/", datadir);
+               if ((status < 1) || (status >= buffer_len - offset))
+                       return (-1);
+               offset += status;
+       }
+
+       status = snprintf (buffer + offset, buffer_len - offset,
+                       "%s/", vl->host);
+       if ((status < 1) || (status >= buffer_len - offset))
+               return (-1);
+       offset += status;
+
+       if (strlen (vl->plugin_instance) > 0)
+               status = snprintf (buffer + offset, buffer_len - offset,
+                               "%s-%s/", vl->plugin, vl->plugin_instance);
+       else
+               status = snprintf (buffer + offset, buffer_len - offset,
+                               "%s/", vl->plugin);
+       if ((status < 1) || (status >= buffer_len - offset))
+               return (-1);
+       offset += status;
+
+       if (strlen (vl->type_instance) > 0)
+               status = snprintf (buffer + offset, buffer_len - offset,
+                               "%s-%s.rrd", ds->type, vl->type_instance);
+       else
+               status = snprintf (buffer + offset, buffer_len - offset,
+                               "%s.rrd", ds->type);
+       if ((status < 1) || (status >= buffer_len - offset))
+               return (-1);
+       offset += status;
+
+       return (0);
+} /* int value_list_to_filename */
+
+static rrd_cache_t *rrd_cache_insert (const char *filename,
+               const char *value)
+{
+       rrd_cache_t *rc = NULL;
+       int new_rc = 0;
+
+       if (cache != NULL)
+               avl_get (cache, filename, (void *) &rc);
+
+       if (rc == NULL)
+       {
+               rc = (rrd_cache_t *) malloc (sizeof (rrd_cache_t));
+               if (rc == NULL)
+                       return (NULL);
+               rc->values_num = 0;
+               rc->values = NULL;
+               rc->first_value = 0;
+               new_rc = 1;
+       }
+
+       rc->values = (char **) realloc ((void *) rc->values,
+                       (rc->values_num + 1) * sizeof (char *));
+       if (rc->values == NULL)
+       {
+               syslog (LOG_ERR, "rrdtool plugin: realloc failed: %s",
+                               strerror (errno));
+               if (cache != NULL)
+               {
+                       void *cache_key = NULL;
+                       avl_remove (cache, filename, &cache_key, NULL);
+                       sfree (cache_key);
+               }
+               free (rc);
+               return (NULL);
+       }
+
+       rc->values[rc->values_num] = strdup (value);
+       if (rc->values[rc->values_num] != NULL)
+               rc->values_num++;
+
+       if (rc->values_num == 1)
+               rc->first_value = time (NULL);
+
+       /* Insert if this is the first value */
+       if ((cache != NULL) && (new_rc == 1))
+       {
+               void *cache_key = strdup (filename);
+
+               if (cache_key == NULL)
+               {
+                       syslog (LOG_ERR, "rrdtool plugin: strdup failed: %s",
+                                       strerror (errno));
+                       sfree (rc->values[0]);
+                       sfree (rc->values);
+                       sfree (rc);
+                       return (NULL);
+               }
+
+               avl_insert (cache, cache_key, rc);
+       }
+
+       DBG ("rrd_cache_insert (%s, %s) = %p", filename, value, (void *) rc);
+
+       return (rc);
+} /* rrd_cache_t *rrd_cache_insert */
+
+static int rrd_write_cache_entry (const char *filename, rrd_cache_t *rc)
+{
+       char **argv;
+       int    argc;
+
+       char *fn;
+       int status;
+
+       int i;
+
+       argc = rc->values_num + 2;
+       argv = (char **) malloc ((argc + 1) * sizeof (char *));
+       if (argv == NULL)
+               return (-1);
+
+       fn = strdup (filename);
+       if (fn == NULL)
+       {
+               free (argv);
+               return (-1);
+       }
+
+       argv[0] = "update";
+       argv[1] = fn;
+       memcpy (argv + 2, rc->values, rc->values_num * sizeof (char *));
+       argv[argc] = NULL;
+
+       DBG ("rrd_update (argc = %i, argv = %p)", argc, (void *) argv);
+
+       optind = 0; /* bug in librrd? */
+       rrd_clear_error ();
+       status = rrd_update (argc, argv);
+
+       free (argv);
+       free (fn);
+
+       /* Free the value list of `rc' */
+       for (i = 0; i < rc->values_num; i++)
+               free (rc->values[i]);
+       free (rc->values);
+       rc->values = NULL;
+       rc->values_num = 0;
+
+       if (status != 0)
+       {
+               syslog (LOG_WARNING, "rrd_update failed: %s: %s",
+                               filename, rrd_get_error ());
+               return (-1);
+       }
+
+       return (0);
+} /* int rrd_write_cache_entry */
+
+static void rrd_cache_flush (int timeout)
+{
+       rrd_cache_t *rc;
+       time_t       now;
+
+       char **keys = NULL;
+       int    keys_num = 0;
+
+       char *key;
+       avl_iterator_t *iter;
+       int i;
+
+       if (cache == NULL)
+               return;
+
+       DBG ("Flushing cache, timeout = %i", timeout);
+
+       now = time (NULL);
+
+       /* Build a list of entries to be flushed */
+       iter = avl_get_iterator (cache);
+       while (avl_iterator_next (iter, (void *) &key, (void *) &rc) == 0)
+       {
+               DBG ("key = %s; age = %i;", key, now - rc->first_value);
+               if ((now - rc->first_value) >= timeout)
+               {
+                       keys = (char **) realloc ((void *) keys,
+                                       (keys_num + 1) * sizeof (char *));
+                       if (keys == NULL)
+                       {
+                               DBG ("realloc failed: %s", strerror (errno));
+                               syslog (LOG_ERR, "rrdtool plugin: "
+                                               "realloc failed: %s",
+                                               strerror (errno));
+                               avl_iterator_destroy (iter);
+                               return;
+                       }
+                       keys[keys_num] = key;
+                       keys_num++;
+               }
+       } /* while (avl_iterator_next) */
+       avl_iterator_destroy (iter);
+       
+       for (i = 0; i < keys_num; i++)
+       {
+               if (avl_remove (cache, keys[i], (void *) &key, (void *) &rc) != 0)
+               {
+                       DBG ("avl_remove (%s) failed.", keys[i]);
+                       continue;
+               }
+
+               rrd_write_cache_entry (keys[i], rc);
+               /* rc's value-list is free's by `rrd_write_cache_entry' */
+               sfree (rc);
+               sfree (key);
+               keys[i] = NULL;
+       } /* for (i = 0..keys_num) */
+
+       free (keys);
+       DBG ("Flushed %i value(s)", keys_num);
+
+       cache_flush_last = now;
+} /* void rrd_cache_flush */
+
+static int rrd_write (const data_set_t *ds, const value_list_t *vl)
+{
+       struct stat  statbuf;
+       char         filename[512];
+       char         values[512];
+       rrd_cache_t *rc;
+       time_t       now;
+
+       if (value_list_to_filename (filename, sizeof (filename), ds, vl) != 0)
+               return (-1);
+
+       if (value_list_to_string (values, sizeof (values), ds, vl) != 0)
+               return (-1);
+
+       if (stat (filename, &statbuf) == -1)
+       {
+               if (errno == ENOENT)
+               {
+                       if (rrd_create_file (filename, ds))
+                               return (-1);
+               }
+               else
+               {
+                       syslog (LOG_ERR, "stat(%s) failed: %s",
+                                       filename, strerror (errno));
+                       return (-1);
+               }
+       }
+       else if (!S_ISREG (statbuf.st_mode))
+       {
+               syslog (LOG_ERR, "stat(%s): Not a regular file!",
+                               filename);
+               return (-1);
+       }
+
+       rc = rrd_cache_insert (filename, values);
+       if (rc == NULL)
+               return (-1);
+
+       if (cache == NULL)
+       {
+               rrd_write_cache_entry (filename, rc);
+               /* rc's value-list is free's by `rrd_write_cache_entry' */
+               sfree (rc);
+               return (0);
+       }
+
+       now = time (NULL);
+
+       DBG ("age (%s) = %i", filename, now - rc->first_value);
+
+       /* `rc' is not free'd here, because we'll likely reuse it. If not, then
+        * the next flush will remove this entry.  */
+       if ((now - rc->first_value) >= cache_timeout)
+               rrd_write_cache_entry (filename, rc);
+
+       if ((now - cache_flush_last) >= cache_flush_timeout)
+               rrd_cache_flush (cache_flush_timeout);
+
+       return (0);
+} /* int rrd_write */
+
+static int rrd_config (const char *key, const char *value)
+{
+       if (strcasecmp ("CacheTimeout", key) == 0)
+       {
+               int tmp = atoi (value);
+               if (tmp < 0)
+               {
+                       fprintf (stderr, "rrdtool: `CacheTimeout' must "
+                                       "be greater than 0.\n");
+                       return (1);
+               }
+               cache_timeout = tmp;
+       }
+       else if (strcasecmp ("CacheFlush", key) == 0)
+       {
+               int tmp = atoi (value);
+               if (tmp < 0)
+               {
+                       fprintf (stderr, "rrdtool: `CacheFlush' must "
+                                       "be greater than 0.\n");
+                       return (1);
+               }
+               cache_flush_timeout = tmp;
+       }
+       else if (strcasecmp ("DataDir", key) == 0)
+       {
+               if (datadir != NULL)
+                       free (datadir);
+               datadir = strdup (value);
+               if (datadir != NULL)
+               {
+                       int len = strlen (datadir);
+                       while ((len > 0) && (datadir[len - 1] == '/'))
+                       {
+                               len--;
+                               datadir[len] = '\0';
+                       }
+                       if (len <= 0)
+                       {
+                               free (datadir);
+                               datadir = NULL;
+                       }
+               }
+       }
+       else if (strcasecmp ("StepSize", key) == 0)
+       {
+               int tmp = atoi (value);
+               if (tmp <= 0)
+               {
+                       fprintf (stderr, "rrdtool: `StepSize' must "
+                                       "be greater than 0.\n");
+                       return (1);
+               }
+               stepsize = tmp;
+       }
+       else if (strcasecmp ("HeartBeat", key) == 0)
+       {
+               int tmp = atoi (value);
+               if (tmp <= 0)
+               {
+                       fprintf (stderr, "rrdtool: `HeartBeat' must "
+                                       "be greater than 0.\n");
+                       return (1);
+               }
+               heartbeat = tmp;
+       }
+       else if (strcasecmp ("RRARows", key) == 0)
+       {
+               int tmp = atoi (value);
+               if (tmp <= 0)
+               {
+                       fprintf (stderr, "rrdtool: `RRARows' must "
+                                       "be greater than 0.\n");
+                       return (1);
+               }
+               rrarows = tmp;
+       }
+       else if (strcasecmp ("XFF", key) == 0)
+       {
+               double tmp = atof (value);
+               if ((tmp < 0.0) || (tmp >= 1.0))
+               {
+                       fprintf (stderr, "rrdtool: `XFF' must "
+                                       "be in the range 0 to 1 (exclusive).");
+                       return (1);
+               }
+               xff = tmp;
+       }
+       else
+       {
+               return (-1);
+       }
+       return (0);
+} /* int rrd_config */
+
+static int rrd_shutdown (void)
+{
+       rrd_cache_flush (-1);
+       if (cache != NULL)
+               avl_destroy (cache);
+       cache = NULL;
+
+       return (0);
+} /* int rrd_shutdown */
+
+static int rrd_init (void)
+{
+       if (stepsize <= 0)
+               stepsize = interval_g;
+       if (heartbeat <= 0)
+               heartbeat = 2 * interval_g;
+
+       if (heartbeat < interval_g)
+               syslog (LOG_WARNING, "rrdtool plugin: Your `heartbeat' is "
+                               "smaller than your `interval'. This will "
+                               "likely cause problems.");
+       else if (stepsize < interval_g)
+               syslog (LOG_WARNING, "rrdtool plugin: Your `stepsize' is "
+                               "smaller than your `interval'. This will "
+                               "create needlessly big RRD-files.");
+
+       if (cache_timeout < 2)
+       {
+               cache_timeout = 0;
+               cache_flush_timeout = 0;
+       }
+       else
+       {
+               if (cache_flush_timeout < cache_timeout)
+                       cache_flush_timeout = 10 * cache_timeout;
+
+               cache = avl_create ((int (*) (const void *, const void *)) strcmp);
+               cache_flush_last = time (NULL);
+               plugin_register_shutdown ("rrdtool", rrd_shutdown);
+       }
+
+       DBG ("datadir = %s; stepsize = %i; heartbeat = %i; rrarows = %i; xff = %lf;",
+                       (datadir == NULL) ? "(null)" : datadir,
+                       stepsize, heartbeat, rrarows, xff);
+
+       return (0);
+} /* int rrd_init */
+
+void module_register (void)
+{
+       plugin_register_config ("rrdtool", rrd_config,
+                       config_keys, config_keys_num);
+       plugin_register_init ("rrdtool", rrd_init);
+       plugin_register_write ("rrdtool", rrd_write);
+}
index 66cd5b2..b1454a6 100644 (file)
@@ -1,11 +1,10 @@
 /**
  * collectd - src/sensors.c
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -36,9 +35,6 @@
 #include "utils_ignorelist.h"
 #include "utils_debug.h"
 
-#define MODULE_NAME "sensors"
-#define MODULE_NAME_VOLTAGE MODULE_NAME"_voltage"
-
 #if defined(HAVE_SENSORS_SENSORS_H)
 # include <sensors/sensors.h>
 #else
 # define SENSORS_HAVE_READ 0
 #endif
 
-#define BUFSIZE 512
+static data_source_t data_source_fanspeed[1] =
+{
+       {"value", DS_TYPE_GAUGE, 0, NAN}
+};
 
-/* temperature and fan sensors */
-static char *ds_def[] =
+static data_set_t fanspeed_ds =
 {
-       "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
-       NULL
+       "fanspeed", 1, data_source_fanspeed
 };
-static int ds_num = 1;
 
-/* voltage sensors */
-static char *sensor_voltage_ds_def[] = 
+static data_source_t data_source_temperature[1] =
 {
-       "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":U:U",
-       NULL
+       {"value", DS_TYPE_GAUGE, -273.15, NAN}
 };
-static int sensor_voltage_ds_num = 1;
 
-/* old naming */
-static char *old_filename_format = "sensors-%s.rrd";
-/* end old naming */
+static data_set_t temperature_ds =
+{
+       "temperature", 1, data_source_temperature
+};
 
-/* new naming <chip-bus-address/type-feature */
-static char *extended_filename_format = "lm_sensors-%s.rrd";
+static data_source_t data_source_voltage[1] =
+{
+       {"value", DS_TYPE_GAUGE, NAN, NAN}
+};
 
-#define SENSOR_TYPE_UNKNOWN 0
-#define SENSOR_TYPE_VOLTAGE 1
-#define SENSOR_TYPE_FANSPEED 2
-#define SENSOR_TYPE_TEMPERATURE 3
+static data_set_t voltage_ds =
+{
+       "voltage", 1, data_source_voltage
+};
 
 #if SENSORS_HAVE_READ
-static char *sensor_type_prefix[] =
+#define SENSOR_TYPE_VOLTAGE     0
+#define SENSOR_TYPE_FANSPEED    1
+#define SENSOR_TYPE_TEMPERATURE 2
+#define SENSOR_TYPE_UNKNOWN     3
+
+static char *sensor_to_type[] =
 {
-       "unknown",
        "voltage",
        "fanspeed",
        "temperature",
        NULL
 };
-#endif
 
-typedef struct sensors_labeltypes {
+struct sensors_labeltypes_s
+{
        char *label;
        int type;
-} sensors_labeltypes;
+};
+typedef struct sensors_labeltypes_s sensors_labeltypes_t;
 
 /*
  * finite list of known labels extracted from lm_sensors
  */
-#if SENSORS_HAVE_READ
-static sensors_labeltypes known_features[] = 
+static sensors_labeltypes_t known_features[] = 
 {
        { "fan1", SENSOR_TYPE_FANSPEED },
        { "fan2", SENSOR_TYPE_FANSPEED },
@@ -155,33 +155,23 @@ static sensors_labeltypes known_features[] =
        { "2.5V", SENSOR_TYPE_VOLTAGE },
        { "2.0V", SENSOR_TYPE_VOLTAGE },
        { "12V", SENSOR_TYPE_VOLTAGE },
-       { 0, -1 }
+       { (char *) 0, SENSOR_TYPE_UNKNOWN }
 };
-#endif
 /* end new naming */
 
-static char *config_keys[] =
+static const char *config_keys[] =
 {
        "Sensor",
        "IgnoreSelected",
-       "ExtendedSensorNaming",
        NULL
 };
-static int config_keys_num = 3;
+static int config_keys_num = 2;
 
 static ignorelist_t *sensor_list;
 
-/* 
- * sensor_extended_naming:
- * 0 => default is to create chip-feature
- * 1 => use new naming scheme chip-bus-address/type-feature
- */
-static int sensor_extended_naming = 0;
-
-#if SENSORS_HAVE_READ
-#  ifndef SENSORS_CONF_PATH
-#    define SENSORS_CONF_PATH "/etc/sensors.conf"
-#  endif
+#ifndef SENSORS_CONF_PATH
+# define SENSORS_CONF_PATH "/etc/sensors.conf"
+#endif
 
 static const char *conffile = SENSORS_CONF_PATH;
 /* SENSORS_CONF_PATH */
@@ -200,9 +190,8 @@ typedef struct featurelist
 } featurelist_t;
 
 featurelist_t *first_feature = NULL;
-#endif /* if SENSORS_HAVE_READ */
 
-static int sensors_config (char *key, char *value)
+static int sensors_config (const char *key, const char *value)
 {
        if (sensor_list == NULL)
                sensor_list = ignorelist_create (1);
@@ -211,7 +200,8 @@ static int sensors_config (char *key, char *value)
        {
                if (ignorelist_add (sensor_list, value))
                {
-                       syslog (LOG_EMERG, MODULE_NAME": Cannot add value to ignorelist.");
+                       syslog (LOG_ERR, "sensors plugin: "
+                                       "Cannot add value to ignorelist.");
                        return (1);
                }
        }
@@ -223,15 +213,6 @@ static int sensors_config (char *key, char *value)
                                || (strcasecmp (value, "On") == 0))
                        ignorelist_set_invert (sensor_list, 0);
        }
-       else if (strcasecmp (key, "ExtendedSensorNaming") == 0)
-       {
-               if ((strcasecmp (value, "True") == 0)
-                               || (strcasecmp (value, "Yes") == 0)
-                               || (strcasecmp (value, "On") == 0))
-                       sensor_extended_naming = 1;
-               else
-                       sensor_extended_naming = 0;
-       }
        else
        {
                return (-1);
@@ -240,7 +221,6 @@ static int sensors_config (char *key, char *value)
        return (0);
 }
 
-#if SENSORS_HAVE_READ
 void sensors_free_features (void)
 {
        featurelist_t *thisft;
@@ -277,7 +257,7 @@ static void sensors_load_conf (void)
        status = stat (conffile, &statbuf);
        if (status != 0)
        {
-               syslog (LOG_ERR, MODULE_NAME": stat(%s) failed: %s",
+               syslog (LOG_ERR, "sensors plugin: stat (%s) failed: %s",
                                conffile, strerror (errno));
                sensors_config_mtime = 0;
        }
@@ -288,7 +268,7 @@ static void sensors_load_conf (void)
 
        if (sensors_config_mtime != 0)
        {
-               syslog (LOG_NOTICE, MODULE_NAME": Reloading config from %s",
+               syslog (LOG_NOTICE, "sensors plugin: Reloading config from %s",
                                conffile);
                sensors_free_features ();
                sensors_config_mtime = 0;
@@ -297,7 +277,7 @@ static void sensors_load_conf (void)
        fh = fopen (conffile, "r");
        if (fh == NULL)
        {
-               syslog (LOG_ERR, MODULE_NAME": fopen(%s) failed: %s",
+               syslog (LOG_ERR, "sensors plugin: fopen(%s) failed: %s",
                                conffile, strerror(errno));
                return;
        }
@@ -306,7 +286,7 @@ static void sensors_load_conf (void)
        fclose (fh);
        if (status != 0)
        {
-               syslog (LOG_ERR, MODULE_NAME": Cannot initialize sensors. "
+               syslog (LOG_ERR, "sensors plugin: Cannot initialize sensors. "
                                "Data will not be collected.");
                return;
        }
@@ -340,13 +320,13 @@ static void sensors_load_conf (void)
 
                                DBG ("Adding feature: %s-%s-%s",
                                                chip->prefix,
-                                               sensor_type_prefix[known_features[i].type],
+                                               sensor_to_type[known_features[i].type],
                                                data->name);
 
                                if ((new_feature = (featurelist_t *) malloc (sizeof (featurelist_t))) == NULL)
                                {
                                        DBG ("malloc: %s", strerror (errno));
-                                       syslog (LOG_ERR, MODULE_NAME":  malloc: %s",
+                                       syslog (LOG_ERR, "sensors plugin:  malloc: %s",
                                                        strerror (errno));
                                        break;
                                }
@@ -376,107 +356,49 @@ static void sensors_load_conf (void)
        if (first_feature == NULL)
        {
                sensors_cleanup ();
-               syslog (LOG_INFO, MODULE_NAME": lm_sensors reports no features. "
-                       "Data will not be collected.");
+               syslog (LOG_INFO, "sensors plugin: lm_sensors reports no "
+                               "features. Data will not be collected.");
        }
 } /* void sensors_load_conf */
-#endif /* if SENSORS_HAVE_READ */
 
-static void collectd_sensors_init (void)
+static int sensors_shutdown (void)
 {
-       return;
-}
-
-static void sensors_shutdown (void)
-{
-#if SENSORS_HAVE_READ
        sensors_free_features ();
-#endif /* if SENSORS_HAVE_READ */
-
-       if (NULL != sensor_list)
-               ignorelist_free (sensor_list);
-}
-
-static void sensors_voltage_write (char *host, char *inst, char *val)
-{
-       char file[BUFSIZE];
-       int status;
-
-       /* skip ignored in our config */
-       if ((NULL != sensor_list) && ignorelist_match (sensor_list, inst))
-               return;
-
-       /* extended sensor naming */
-       if(sensor_extended_naming)
-               status = snprintf (file, BUFSIZE, extended_filename_format, inst);
-       else
-               status = snprintf (file, BUFSIZE, old_filename_format, inst);
-
-       if ((status < 1) || (status >= BUFSIZE))
-               return;
+       ignorelist_free (sensor_list);
 
-       rrd_update_file (host, file, val, sensor_voltage_ds_def, sensor_voltage_ds_num);
-}
-
-static void sensors_write (char *host, char *inst, char *val)
-{
-       char file[BUFSIZE];
-       int status;
-
-       /* skip ignored in our config */
-       if ((NULL != sensor_list) && ignorelist_match (sensor_list, inst))
-               return;
-
-       /* extended sensor naming */
-       if (sensor_extended_naming)
-               status = snprintf (file, BUFSIZE, extended_filename_format, inst);
-       else
-               status = snprintf (file, BUFSIZE, old_filename_format, inst);
-
-       if ((status < 1) || (status >= BUFSIZE))
-               return;
-
-       rrd_update_file (host, file, val, ds_def, ds_num);
-}
+       return (0);
+} /* int sensors_shutdown */
 
-#if SENSORS_HAVE_READ
-static void sensors_submit (const char *feat_name,
-               const char *chip_prefix, double value, int type)
+static void sensors_submit (const char *plugin_instance,
+               const char *type, const char *type_instance,
+               double val)
 {
-       char buf[BUFSIZE];
-       char inst[BUFSIZE];
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       if (snprintf (inst, BUFSIZE, "%s-%s", chip_prefix, feat_name)
-                       >= BUFSIZE)
+       if (ignorelist_match (sensor_list, type_instance))
                return;
 
-       /* skip ignored in our config */
-       if ((NULL != sensor_list) && ignorelist_match (sensor_list, inst))
-               return;
+       values[0].gauge = val;
 
-       if (snprintf (buf, BUFSIZE, "%u:%.3f", (unsigned int) curtime,
-                               value) >= BUFSIZE)
-               return;
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "sensors");
+       strcpy (vl.plugin_instance, plugin_instance);
+       strcpy (vl.type_instance, type_instance);
 
-       if (type == SENSOR_TYPE_VOLTAGE)
-       {
-               DBG ("%s: %s/%s, %s", MODULE_NAME_VOLTAGE,
-                               sensor_type_prefix[type], inst, buf);
-               plugin_submit (MODULE_NAME_VOLTAGE, inst, buf);
-       }
-       else
-       {
-               DBG ("%s: %s/%s, %s", MODULE_NAME,
-                               sensor_type_prefix[type], inst, buf);
-               plugin_submit (MODULE_NAME, inst, buf);
-       }
-}
+       plugin_dispatch_values (type, &vl);
+} /* void sensors_submit */
 
-static void sensors_read (void)
+static int sensors_read (void)
 {
        featurelist_t *feature;
        double value;
-       char chip_fullprefix[BUFSIZE];
+
+       char plugin_instance[DATA_MAX_NAME_LEN];
+       char type_instance[DATA_MAX_NAME_LEN];
 
        sensors_load_conf ();
 
@@ -485,62 +407,56 @@ static void sensors_read (void)
                if (sensors_get_feature (*feature->chip, feature->data->number, &value) < 0)
                        continue;
 
-               if (sensor_extended_naming)
+               /* full chip name logic borrowed from lm_sensors */
+               if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
                {
-                       /* full chip name logic borrowed from lm_sensors */
-                       if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
-                       {
-                               if (snprintf (chip_fullprefix, BUFSIZE, "%s-isa-%04x/%s",
-                                                       feature->chip->prefix,
-                                                       feature->chip->addr,
-                                                       sensor_type_prefix[feature->type])
-                                               >= BUFSIZE)
-                                       continue;
-                       }
-                       else if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_DUMMY)
-                       {
-                               if (snprintf (chip_fullprefix, BUFSIZE, "%s-%s-%04x/%s",
-                                                       feature->chip->prefix,
-                                                       feature->chip->busname,
-                                                       feature->chip->addr,
-                                                       sensor_type_prefix[feature->type])
-                                               >= BUFSIZE)
-                                       continue;
-                       }
-                       else
-                       {
-                               if (snprintf (chip_fullprefix, BUFSIZE, "%s-i2c-%d-%02x/%s",
-                                                       feature->chip->prefix,
-                                                       feature->chip->bus,
-                                                       feature->chip->addr,
-                                                       sensor_type_prefix[feature->type])
-                                               >= BUFSIZE)
-                                       continue;
-                       }
-
-                       sensors_submit (feature->data->name,
-                                       chip_fullprefix,
-                                       value, feature->type);
+                       if (snprintf (plugin_instance, DATA_MAX_NAME_LEN, "%s-isa-%04x",
+                                               feature->chip->prefix,
+                                               feature->chip->addr)
+                                       >= 512)
+                               continue;
+               }
+               else if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_DUMMY)
+               {
+                       if (snprintf (plugin_instance, 512, "%s-%s-%04x",
+                                               feature->chip->prefix,
+                                               feature->chip->busname,
+                                               feature->chip->addr)
+                                       >= 512)
+                               continue;
                }
                else
                {
-                       sensors_submit (feature->data->name,
-                                       feature->chip->prefix,
-                                       value, feature->type);
+                       if (snprintf (plugin_instance, 512, "%s-i2c-%d-%02x",
+                                               feature->chip->prefix,
+                                               feature->chip->bus,
+                                               feature->chip->addr)
+                                       >= 512)
+                               continue;
                }
+
+               strncpy (type_instance, feature->data->name, DATA_MAX_NAME_LEN);
+
+               sensors_submit (plugin_instance,
+                               sensor_to_type[feature->type],
+                               type_instance,
+                               value);
        } /* for feature = first_feature .. NULL */
-} /* void sensors_read */
-#else
-# define sensors_read NULL
+
+       return (0);
+} /* int sensors_read */
 #endif /* SENSORS_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, collectd_sensors_init, sensors_read, sensors_write);
-       plugin_register (MODULE_NAME_VOLTAGE, NULL, NULL, sensors_voltage_write);
-       plugin_register_shutdown (MODULE_NAME, sensors_shutdown);
-       cf_register (MODULE_NAME, sensors_config, config_keys, config_keys_num);
-}
+       plugin_register_data_set (&fanspeed_ds);
+       plugin_register_data_set (&temperature_ds);
+       plugin_register_data_set (&voltage_ds);
 
-#undef BUFSIZE
-#undef MODULE_NAME
+#if SENSORS_HAVE_READ
+       plugin_register_config ("sensors", sensors_config,
+                       config_keys, config_keys_num);
+       plugin_register_read ("sensors", sensors_read);
+       plugin_register_shutdown ("sensors", sensors_shutdown);
+#endif
+} /* void module_register */
index 0c6050d..8f8e433 100644 (file)
 #include "common.h"
 #include "plugin.h"
 
-#define MODULE_NAME "serial"
-
 #if defined(KERNEL_LINUX)
 # define SERIAL_HAVE_READ 1
 #else
 # define SERIAL_HAVE_READ 0
 #endif
 
-static char *serial_filename_template = "serial-%s.rrd";
-
-static char *ds_def[] =
+static data_source_t octets_dsrc[2] =
 {
-       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+       {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
 };
-static int ds_num = 2;
 
-static void serial_init (void)
+static data_set_t octets_ds =
 {
-       return;
-}
+       "serial_octets", 2, octets_dsrc
+};
 
-static void serial_write (char *host, char *inst, char *val)
+#if SERIAL_HAVE_READ
+static void serial_submit (const char *type_instance,
+               counter_t rx, counter_t tx)
 {
-       char file[512];
-       int status;
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       status = snprintf (file, 512, serial_filename_template, inst);
-       if (status < 1)
-               return;
-       else if (status >= 512)
-               return;
+       values[0].counter = rx;
+       values[1].counter = tx;
 
-       rrd_update_file (host, file, val, ds_def, ds_num);
-}
+       vl.values = values;
+       vl.values_len = 2;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "serial");
+       strncpy (vl.type_instance, type_instance,
+                       sizeof (vl.type_instance));
 
-#if SERIAL_HAVE_READ
-#define BUFSIZE 512
-static void serial_submit (char *device,
-               unsigned long long incoming,
-               unsigned long long outgoing)
-{
-       char buf[BUFSIZE];
-        
-       if (snprintf (buf, BUFSIZE, "%u:%llu:%llu", (unsigned int) curtime,
-                               incoming, outgoing) >= BUFSIZE)
-               return;
-
-       plugin_submit (MODULE_NAME, device, buf);
+       plugin_dispatch_values ("serial_octets", &vl);
 }
-#undef BUFSIZE
 
-static void serial_read (void)
+static int serial_read (void)
 {
 #ifdef KERNEL_LINUX
-
        FILE *fh;
        char buffer[1024];
-       unsigned long long incoming, outgoing;
+
+       counter_t rx = 0;
+       counter_t tx = 0;
        
        char *fields[16];
        int i, numfields;
@@ -95,20 +81,13 @@ static void serial_read (void)
                (fh = fopen ("/proc/tty/driver/ttyS", "r")) == NULL)
        {
                syslog (LOG_WARNING, "serial: fopen: %s", strerror (errno));
-               return;
+               return (-1);
        }
 
-       while (fgets (buffer, 1024, fh) != NULL)
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
        {
                int have_rx = 0, have_tx = 0;
 
-               /* stupid compiler:
-                * serial.c:87: warning: 'incoming' may be used uninitialized in this function
-                * serial.c:87: warning: 'outgoing' may be used uninitialized in this function
-                */
-               incoming = 0ULL;
-               outgoing = 0ULL;
-
                numfields = strsplit (buffer, fields, 16);
 
                if (numfields < 6)
@@ -133,12 +112,12 @@ static void serial_read (void)
 
                        if (strncmp (fields[i], "tx:", 3) == 0)
                        {
-                               outgoing = atoll (fields[i] + 3);
+                               tx = atoll (fields[i] + 3);
                                have_tx++;
                        }
                        else if (strncmp (fields[i], "rx:", 3) == 0)
                        {
-                               incoming = atoll (fields[i] + 3);
+                               rx = atoll (fields[i] + 3);
                                have_rx++;
                        }
                }
@@ -146,19 +125,20 @@ static void serial_read (void)
                if ((have_rx == 0) || (have_tx == 0))
                        continue;
 
-               serial_submit (fields[0], incoming, outgoing);
+               serial_submit (fields[0], rx, tx);
        }
 
        fclose (fh);
+       return (0);
 #endif /* KERNEL_LINUX */
-}
-#else
-# define serial_read NULL
+} /* int serial_read */
 #endif /* SERIAL_HAVE_READ */
 
 void module_register (void)
 {
-   plugin_register (MODULE_NAME, serial_init, serial_read, serial_write);
-}
+       plugin_register_data_set (&octets_ds);
 
-#undef MODULE_NAME
+#if SERIAL_HAVE_READ
+       plugin_register_read ("serial", serial_read);
+#endif /* SERIAL_HAVE_READ */
+}
index 43275fc..8e04044 100644 (file)
@@ -1,11 +1,10 @@
 /**
  * collectd - src/swap.c
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -37,8 +36,6 @@
 #  include <kvm.h>
 #endif
 
-#define MODULE_NAME "swap"
-
 #if KERNEL_LINUX || HAVE_LIBKSTAT || defined(VM_SWAPUSAGE) || HAVE_LIBKVM || HAVE_LIBSTATGRAB
 # define SWAP_HAVE_READ 1
 #else
 #undef  MAX
 #define MAX(x,y) ((x) > (y) ? (x) : (y))
 
-static char *swap_file = "swap.rrd";
+static data_source_t data_source[1] =
+{
+       {"value", DS_TYPE_GAUGE, 0, 1099511627776.0}
+};
 
-/* 1099511627776 == 1TB ought to be enough for anyone ;) */
-static char *ds_def[] =
+static data_set_t data_set =
 {
-       "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
-       "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
-       "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
-       "DS:resv:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
-       NULL
+       "swap", 1, data_source
 };
-static int ds_num = 4;
 
+#if SWAP_HAVE_READ
 #if KERNEL_LINUX
 /* No global variables */
 /* #endif KERNEL_LINUX */
@@ -83,7 +78,7 @@ int kvm_pagesize;
 /* No global variables */
 #endif /* HAVE_LIBSTATGRAB */
 
-static void swap_init (void)
+static int swap_init (void)
 {
 #if KERNEL_LINUX
        /* No init stuff */
@@ -117,7 +112,7 @@ static void swap_init (void)
                        == NULL)
        {
                syslog (LOG_ERR, "swap plugin: kvm_open failed.");
-               return;
+               return (-1);
        }
 /* #endif HAVE_LIBKVM */
 
@@ -125,30 +120,27 @@ static void swap_init (void)
        /* No init stuff */
 #endif /* HAVE_LIBSTATGRAB */
 
-       return;
+       return (0);
 }
 
-static void swap_write (char *host, char *inst, char *val)
+static void swap_submit (const char *type_instance, double value)
 {
-       rrd_update_file (host, swap_file, val, ds_def, ds_num);
-}
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-#if SWAP_HAVE_READ
-static void swap_submit (unsigned long long swap_used,
-               unsigned long long swap_free,
-               unsigned long long swap_cached,
-               unsigned long long swap_resv)
-{
-       char buffer[512];
+       values[0].gauge = value;
 
-       if (snprintf (buffer, 512, "%u:%llu:%llu:%llu:%llu", (unsigned int) curtime,
-                               swap_used, swap_free, swap_cached, swap_resv) >= 512)
-               return;
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "swap");
+       strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
-       plugin_submit (MODULE_NAME, "-", buffer);
-}
+       plugin_dispatch_values ("swap", &vl);
+} /* void swap_submit */
 
-static void swap_read (void)
+static int swap_read (void)
 {
 #if KERNEL_LINUX
        FILE *fh;
@@ -165,7 +157,7 @@ static void swap_read (void)
        if ((fh = fopen ("/proc/meminfo", "r")) == NULL)
        {
                syslog (LOG_WARNING, "memory: fopen: %s", strerror (errno));
-               return;
+               return (-1);
        }
 
        while (fgets (buffer, 1024, fh) != NULL)
@@ -193,11 +185,13 @@ static void swap_read (void)
                syslog (LOG_WARNING, "memory: fclose: %s", strerror (errno));
 
        if ((swap_total == 0LL) || ((swap_free + swap_cached) > swap_total))
-               return;
+               return (-1);
 
        swap_used = swap_total - (swap_free + swap_cached);
 
-       swap_submit (swap_used, swap_free, swap_cached, -1LL);
+       swap_submit ("used", swap_used);
+       swap_submit ("free", swap_free);
+       swap_submit ("cached", swap_cached);
 /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKSTAT
@@ -211,7 +205,7 @@ static void swap_read (void)
        {
                syslog (LOG_ERR, "swap plugin: swapctl failed: %s",
                                strerror (errno));
-               return;
+               return (-1);
        }
 
        /*
@@ -242,7 +236,9 @@ static void swap_read (void)
        swap_avail  = ai.ani_max - ai.ani_resv;
        swap_avail *= pagesize;
 
-       swap_submit (swap_alloc, swap_avail, -1LL, swap_resv - swap_alloc);
+       swap_submit ("used", swap_alloc);
+       swap_submit ("free", swap_avail);
+       swap_submit ("reserved", swap_resv - swap_alloc);
 /* #endif HAVE_LIBKSTAT */
 
 #elif defined(VM_SWAPUSAGE)
@@ -258,10 +254,11 @@ static void swap_read (void)
        sw_usage_len = sizeof (struct xsw_usage);
 
        if (sysctl (mib, mib_len, &sw_usage, &sw_usage_len, NULL, 0) != 0)
-               return;
+               return (-1);
 
        /* The returned values are bytes. */
-       swap_submit (sw_usage.xsu_used, sw_usage.xsu_avail, -1LL, -1LL);
+       swap_submit ("used", sw_usage.xsu_used);
+       swap_submit ("free", sw_usage.xsu_avail);
 /* #endif VM_SWAPUSAGE */
 
 #elif HAVE_LIBKVM
@@ -273,12 +270,12 @@ static void swap_read (void)
        unsigned long long total;
 
        if (kvm_obj == NULL)
-               return;
+               return (-1);
 
        /* only one structure => only get the grand total, no details */
        status = kvm_getswapinfo (kvm_obj, &data_s, 1, 0);
        if (status == -1)
-               return;
+               return (-1);
 
        total = (unsigned long long) data_s.ksw_total;
        used  = (unsigned long long) data_s.ksw_used;
@@ -288,23 +285,32 @@ static void swap_read (void)
 
        free = total - used;
 
-       swap_submit (used, free, -1LL, -1LL);
+       swap_submit ("used", used);
+       swap_submit ("free", free);
 /* #endif HAVE_LIBKVM */
 
 #elif HAVE_LIBSTATGRAB
        sg_swap_stats *swap;
 
-       if ((swap = sg_get_swap_stats ()) != NULL)
-               swap_submit (swap->used, swap->free, -1LL, -1LL);
+       swap = sg_get_swap_stats ();
+
+       if (swap == NULL)
+               return (-1);
+
+       swap_submit ("used", swap->used);
+       swap_submit ("free", swap->free);
 #endif /* HAVE_LIBSTATGRAB */
-}
-#else
-# define swap_read NULL
+
+       return (0);
+} /* int swap_read */
 #endif /* SWAP_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, swap_init, swap_read, swap_write);
-}
+       plugin_register_data_set (&data_set);
 
-#undef MODULE_NAME
+#if SWAP_HAVE_READ
+       plugin_register_init ("swap", swap_init);
+       plugin_register_read ("swap", swap_read);
+#endif /* SWAP_HAVE_READ */
+}
diff --git a/src/syslog.c b/src/syslog.c
new file mode 100644 (file)
index 0000000..bcf873e
--- /dev/null
@@ -0,0 +1,97 @@
+/**
+ * collectd - src/syslog.c
+ * Copyright (C) 2007  Florian Forster
+ *
+ * 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.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if HAVE_SYSLOG_H
+# include <syslog.h>
+#endif
+
+static int log_level = LOG_DEBUG;
+
+static const char *config_keys[] =
+{
+       "LogLevel"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
+
+static int sl_config (const char *key, const char *value)
+{
+       if (strcasecmp (key, "LogLevel") == 0)
+       {
+               if ((strcasecmp (value, "emerg") == 0)
+                               || (strcasecmp (value, "alert") == 0)
+                               || (strcasecmp (value, "crit") == 0)
+                               || (strcasecmp (value, "err") == 0))
+                       log_level = LOG_ERR;
+               else if (strcasecmp (value, "warning") == 0)
+                       log_level = LOG_WARNING;
+               else if (strcasecmp (value, "notice") == 0)
+                       log_level = LOG_NOTICE;
+               else if (strcasecmp (value, "info") == 0)
+                       log_level = LOG_INFO;
+#if COLLECTD_DEBUG
+               else if (strcasecmp (value, "debug") == 0)
+                       log_level = LOG_DEBUG;
+#endif
+               else
+                       return (1);
+       }
+       else
+               return (-1);
+
+       return (0);
+} /* int sl_config */
+
+static int sl_init (void)
+{
+       openlog ("collectd", LOG_CONS | LOG_PID, LOG_DAEMON);
+
+       return (0);
+}
+
+static void sl_log (int sevetiry, const char *msg)
+{
+       if (sevetiry > log_level)
+               return;
+
+       syslog (sevetiry, "%s", msg);
+} /* void sl_log */
+
+static int sl_shutdown (void)
+{
+       closelog ();
+
+       return (0);
+}
+
+void module_register (void)
+{
+       plugin_register_config ("syslog", sl_config, config_keys, config_keys_num);
+       plugin_register_init ("syslog", sl_init);
+       plugin_register_log ("syslog", sl_log);
+       plugin_register_shutdown ("syslog", sl_shutdown);
+
+       return;
+} /* void module_register(void) */
index b13cdbd..85a63a8 100644 (file)
 #include "common.h"
 #include "plugin.h"
 
-#define MODULE_NAME "tape"
-
 #if defined(HAVE_LIBKSTAT)
 # define TAPE_HAVE_READ 1
 #else
 # define TAPE_HAVE_READ 0
 #endif
 
-static char *tape_filename_template = "tape-%s.rrd";
+/* 2^34 = 17179869184 = ~17.2GByte/s */
+static data_source_t octets_dsrc[2] =
+{
+       {"read",  DS_TYPE_COUNTER, 0, 17179869183.0},
+       {"write", DS_TYPE_COUNTER, 0, 17179869183.0}
+};
+
+static data_set_t octets_ds =
+{
+       "tape_octets", 2, octets_dsrc
+};
+
+static data_source_t operations_dsrc[2] =
+{
+       {"read",  DS_TYPE_COUNTER, 0, 4294967295.0},
+       {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t operations_ds =
+{
+       "tape_ops", 2, operations_dsrc
+};
+
+static data_source_t merged_dsrc[2] =
+{
+       {"read",  DS_TYPE_COUNTER, 0, 4294967295.0},
+       {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t merged_ds =
+{
+       "tape_merged", 2, merged_dsrc
+};
+
+/* max is 1000000us per second. */
+static data_source_t time_dsrc[2] =
+{
+       {"read",  DS_TYPE_COUNTER, 0, 1000000.0},
+       {"write", DS_TYPE_COUNTER, 0, 1000000.0}
+};
 
-/* 104857600 == 100 MB */
-static char *tape_ds_def[] =
+static data_set_t time_ds =
 {
-       "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:rmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:rtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:wmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:wtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       "tape_time", 2, time_dsrc
 };
-static int tape_ds_num = 8;
 
+#if TAPE_HAVE_READ
 #if defined(HAVE_LIBKSTAT)
 #define MAX_NUMTAPE 256
 extern kstat_ctl_t *kc;
@@ -56,7 +84,7 @@ static kstat_t *ksp[MAX_NUMTAPE];
 static int numtape = 0;
 #endif /* HAVE_LIBKSTAT */
 
-static void tape_init (void)
+static int tape_init (void)
 {
 #ifdef HAVE_LIBKSTAT
        kstat_t *ksp_chain;
@@ -64,7 +92,7 @@ static void tape_init (void)
        numtape = 0;
 
        if (kc == NULL)
-               return;
+               return (-1);
 
        for (numtape = 0, ksp_chain = kc->kc_chain;
                        (numtape < MAX_NUMTAPE) && (ksp_chain != NULL);
@@ -78,52 +106,31 @@ static void tape_init (void)
        }
 #endif
 
-       return;
+       return (0);
 }
 
-static void tape_write (char *host, char *inst, char *val)
+static void tape_submit (const char *plugin_instance,
+               const char *type,
+               counter_t read, counter_t write)
 {
-       char file[512];
-       int status;
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       status = snprintf (file, 512, tape_filename_template, inst);
-       if (status < 1)
-               return;
-       else if (status >= 512)
-               return;
-
-       rrd_update_file (host, file, val, tape_ds_def, tape_ds_num);
-}
+       values[0].counter = read;
+       values[1].counter = write;
 
+       vl.values = values;
+       vl.values_len = 2;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "tape");
+       strncpy (vl.plugin_instance, plugin_instance,
+                       sizeof (vl.plugin_instance));
 
-#if TAPE_HAVE_READ
-#define BUFSIZE 512
-static void tape_submit (char *tape_name,
-               unsigned long long read_count,
-               unsigned long long read_merged,
-               unsigned long long read_bytes,
-               unsigned long long read_time,
-               unsigned long long write_count,
-               unsigned long long write_merged,
-               unsigned long long write_bytes,
-               unsigned long long write_time)
+       plugin_dispatch_values (type, &vl);
+} /* void tape_submit */
 
-{
-       char buf[BUFSIZE];
-
-       if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
-                               (unsigned int) curtime,
-                               read_count, read_merged, read_bytes, read_time,
-                               write_count, write_merged, write_bytes,
-                               write_time) >= BUFSIZE)
-               return;
-
-       plugin_submit (MODULE_NAME, tape_name, buf);
-}
-
-#undef BUFSIZE
-
-static void tape_read (void)
+static int tape_read (void)
 {
 
 #if defined(HAVE_LIBKSTAT)
@@ -131,7 +138,10 @@ static void tape_read (void)
        int i;
 
        if (kc == NULL)
-               return;
+               return (-1);
+
+       if (numtape <= 0)
+               return (-1);
 
        for (i = 0; i < numtape; i++)
        {
@@ -139,19 +149,28 @@ static void tape_read (void)
                        continue;
 
                if (strncmp (ksp[i]->ks_class, "tape", 4) == 0)
-                       tape_submit (ksp[i]->ks_name,
-                                       kio.reads,  0LL, kio.nread,    kio.rtime,
-                                       kio.writes, 0LL, kio.nwritten, kio.wtime);
+               {
+                       tape_submit (ksp[i]->ks_name, "tape_octets", kio.reads, kio.writes);
+                       tape_submit (ksp[i]->ks_name, "tape_ops", kio.nreads, kio.nwrites);
+                       /* FIXME: Convert this to microseconds if necessary */
+                       tape_submit (ksp[i]->ks_name, "tape_time", kio.rtime, kio.wtime);
+               }
        }
 #endif /* defined(HAVE_LIBKSTAT) */
+
+       return (0);
 }
-#else
-# define tape_read NULL
 #endif /* TAPE_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, tape_init, tape_read, tape_write);
-}
+       plugin_register_data_set (&octets_ds);
+       plugin_register_data_set (&operations_ds);
+       plugin_register_data_set (&merged_ds);
+       plugin_register_data_set (&time_ds);
 
-#undef MODULE_NAME
+#if TAPE_HAVE_READ
+       plugin_register_init ("tape", tape_init);
+       plugin_register_read ("tape", tape_read);
+#endif /* TAPE_HAVE_READ */
+}
index 14b7dc3..619208c 100644 (file)
@@ -1,11 +1,10 @@
 /**
  * collectd - src/traffic.c
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -47,8 +46,6 @@
 #  include <ifaddrs.h>
 #endif
 
-#define MODULE_NAME "traffic"
-
 /*
  * Various people have reported problems with `getifaddrs' and varying versions
  * of `glibc'. That's why it's disabled by default. Since more statistics are
 # define TRAFFIC_HAVE_READ 0
 #endif
 
-#define BUFSIZE 512
-
 /*
  * (Module-)Global variables
  */
-/* TODO: Move this to `interface-%s/<blah>.rrd' in version 4. */
-static char *bytes_file   = "traffic-%s.rrd";
-static char *packets_file = "interface-%s/if_packets.rrd";
-static char *errors_file  = "interface-%s/if_errors.rrd";
-/* TODO: Maybe implement multicast and broadcast counters */
+/* 2^32 = 4294967296 = ~4.2GByte/s = ~34GBit/s */
+static data_source_t octets_dsrc[2] =
+{
+       {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+       {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
 
-static char *config_keys[] =
+static data_set_t octets_ds =
 {
-       "Interface",
-       "IgnoreSelected",
-       NULL
+       "if_octets", 2, octets_dsrc
 };
-static int config_keys_num = 2;
 
-static char *bytes_ds_def[] =
+static data_source_t packets_dsrc[2] =
 {
-       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+       {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
 };
-static int bytes_ds_num = 2;
 
-static char *packets_ds_def[] =
+static data_set_t packets_ds =
 {
-       "DS:rx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:tx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       NULL
+       "if_packets", 2, packets_dsrc
 };
-static int packets_ds_num = 2;
 
-static char *errors_ds_def[] =
+static data_source_t errors_dsrc[2] =
 {
-       "DS:rx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
-       "DS:tx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+       {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t errors_ds =
+{
+       "if_errors", 2, errors_dsrc
+};
+
+static const char *config_keys[] =
+{
+       "Interface",
+       "IgnoreSelected",
        NULL
 };
-static int errors_ds_num = 2;
+static int config_keys_num = 2;
 
 static char **if_list = NULL;
 static int    if_list_num = 0;
@@ -126,7 +125,7 @@ static kstat_t *ksp[MAX_NUMIF];
 static int numif = 0;
 #endif /* HAVE_LIBKSTAT */
 
-static int traffic_config (char *key, char *value)
+static int interface_config (const char *key, const char *value)
 {
        char **temp;
 
@@ -164,24 +163,17 @@ static int traffic_config (char *key, char *value)
        return (0);
 }
 
-static void traffic_init (void)
+#if HAVE_LIBKSTAT
+static int traffic_init (void)
 {
-#if HAVE_GETIFADDRS
-       /* nothing */
-/* #endif HAVE_GETIFADDRS */
-
-#elif KERNEL_LINUX
-       /* nothing */
-/* #endif KERNEL_LINUX */
-
-#elif HAVE_LIBKSTAT
+#if HAVE_LIBKSTAT
        kstat_t *ksp_chain;
        unsigned long long val;
 
        numif = 0;
 
        if (kc == NULL)
-               return;
+               return (-1);
 
        for (numif = 0, ksp_chain = kc->kc_chain;
                        (numif < MAX_NUMIF) && (ksp_chain != NULL);
@@ -197,14 +189,11 @@ static void traffic_init (void)
                        continue;
                ksp[numif++] = ksp_chain;
        }
-/* #endif HAVE_LIBKSTAT */
-
-#elif HAVE_LIBSTATG
-       /* nothing */
-#endif /* HAVE_LIBSTATG */
+#endif /* HAVE_LIBKSTAT */
 
-       return;
-}
+       return (0);
+} /* int traffic_init */
+#endif /* HAVE_LIBKSTAT */
 
 /*
  * Check if this interface/instance should be ignored. This is called from
@@ -224,101 +213,33 @@ static int check_ignore_if (const char *interface)
                if (strcasecmp (interface, if_list[i]) == 0)
                        return (if_list_action);
        return (1 - if_list_action);
-}
-
-static void generic_write (char *host, char *inst, char *val,
-               char *file_template,
-               char **ds_def, int ds_num)
-{
-       char file[512];
-       int status;
-
-       if (check_ignore_if (inst))
-               return;
-
-       status = snprintf (file, BUFSIZE, file_template, inst);
-       if (status < 1)
-               return;
-       else if (status >= 512)
-               return;
-
-       rrd_update_file (host, file, val, ds_def, ds_num);
-}
-
-static void bytes_write (char *host, char *inst, char *val)
-{
-       generic_write (host, inst, val, bytes_file, bytes_ds_def, bytes_ds_num);
-}
-
-static void packets_write (char *host, char *inst, char *val)
-{
-       generic_write (host, inst, val, packets_file, packets_ds_def, packets_ds_num);
-}
-
-static void errors_write (char *host, char *inst, char *val)
-{
-       generic_write (host, inst, val, errors_file, errors_ds_def, errors_ds_num);
-}
+} /* int check_ignore_if */
 
 #if TRAFFIC_HAVE_READ
-static void bytes_submit (char *dev,
-               unsigned long long rx,
-               unsigned long long tx)
-{
-       char buf[512];
-       int  status;
-
-       if (check_ignore_if (dev))
-               return;
-
-       status = snprintf (buf, 512, "%u:%lld:%lld",
-                               (unsigned int) curtime,
-                               rx, tx);
-       if ((status >= 512) || (status < 1))
-               return;
-
-       plugin_submit (MODULE_NAME, dev, buf);
-}
-
-#if HAVE_GETIFADDRS || KERNEL_LINUX || HAVE_LIBKSTAT
-static void packets_submit (char *dev,
+static void if_submit (const char *dev, const char *type,
                unsigned long long rx,
                unsigned long long tx)
 {
-       char buf[512];
-       int  status;
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
 
        if (check_ignore_if (dev))
                return;
 
-       status = snprintf (buf, 512, "%u:%lld:%lld",
-                       (unsigned int) curtime,
-                       rx, tx);
-       if ((status >= 512) || (status < 1))
-               return;
-       plugin_submit ("if_packets", dev, buf);
-}
-
-static void errors_submit (char *dev,
-               unsigned long long rx,
-               unsigned long long tx)
-{
-       char buf[512];
-       int  status;
+       values[0].counter = rx;
+       values[1].counter = tx;
 
-       if (check_ignore_if (dev))
-               return;
+       vl.values = values;
+       vl.values_len = 2;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "interface");
+       strncpy (vl.type_instance, dev, sizeof (vl.type_instance));
 
-       status = snprintf (buf, 512, "%u:%lld:%lld",
-                       (unsigned int) curtime,
-                       rx, tx);
-       if ((status >= 512) || (status < 1))
-               return;
-       plugin_submit ("if_errors", dev, buf);
-}
-#endif /* HAVE_GETIFADDRS || KERNEL_LINUX || HAVE_LIBKSTAT */
+       plugin_dispatch_values (type, &vl);
+} /* void if_submit */
 
-static void traffic_read (void)
+static int traffic_read (void)
 {
 #if HAVE_GETIFADDRS
        struct ifaddrs *if_list;
@@ -350,20 +271,20 @@ static void traffic_read (void)
        struct IFA_DATA *if_data;
 
        if (getifaddrs (&if_list) != 0)
-               return;
+               return (-1);
 
        for (if_ptr = if_list; if_ptr != NULL; if_ptr = if_ptr->ifa_next)
        {
                if ((if_data = (struct IFA_DATA *) if_ptr->ifa_data) == NULL)
                        continue;
 
-               bytes_submit (if_ptr->ifa_name,
+               if_submit (if_ptr->ifa_name, "if_octets",
                                if_data->IFA_RX_BYTES,
                                if_data->IFA_TX_BYTES);
-               packets_submit (if_ptr->ifa_name,
+               if_submit (if_ptr->ifa_name, "if_packets",
                                if_data->IFA_RX_PACKT,
                                if_data->IFA_TX_PACKT);
-               errors_submit (if_ptr->ifa_name,
+               if_submit (if_ptr->ifa_name, "if_errors",
                                if_data->IFA_RX_ERROR,
                                if_data->IFA_TX_ERROR);
        }
@@ -384,7 +305,7 @@ static void traffic_read (void)
        if ((fh = fopen ("/proc/net/dev", "r")) == NULL)
        {
                syslog (LOG_WARNING, "traffic: fopen: %s", strerror (errno));
-               return;
+               return (-1);
        }
 
        while (fgets (buffer, 1024, fh) != NULL)
@@ -408,15 +329,15 @@ static void traffic_read (void)
 
                incoming = atoll (fields[0]);
                outgoing = atoll (fields[8]);
-               bytes_submit (device, incoming, outgoing);
+               if_submit (device, "if_octets", incoming, outgoing);
 
                incoming = atoll (fields[1]);
                outgoing = atoll (fields[9]);
-               packets_submit (device, incoming, outgoing);
+               if_submit (device, "if_packets", incoming, outgoing);
 
                incoming = atoll (fields[2]);
                outgoing = atoll (fields[10]);
-               errors_submit (device, incoming, outgoing);
+               if_submit (device, "if_errors", incoming, outgoing);
        }
 
        fclose (fh);
@@ -438,17 +359,17 @@ static void traffic_read (void)
                rx = get_kstat_value (ksp[i], "rbytes");
                tx = get_kstat_value (ksp[i], "obytes");
                if ((rx != -1LL) || (tx != -1LL))
-                       bytes_submit (ksp[i]->ks_name, rx, tx);
+                       if_submit (ksp[i]->ks_name, "if_octets", rx, tx);
 
                rx = get_kstat_value (ksp[i], "ipackets");
                tx = get_kstat_value (ksp[i], "opackets");
                if ((rx != -1LL) || (tx != -1LL))
-                       packets_submit (ksp[i]->ks_name, rx, tx);
+                       if_submit (ksp[i]->ks_name, "if_packets", rx, tx);
 
                rx = get_kstat_value (ksp[i], "ierrors");
                tx = get_kstat_value (ksp[i], "oerrors");
                if ((rx != -1LL) || (tx != -1LL))
-                       errors_submit (ksp[i]->ks_name, rx, tx);
+                       if_submit (ksp[i]->ks_name, "if_errors", rx, tx);
        }
 /* #endif HAVE_LIBKSTAT */
 
@@ -459,20 +380,27 @@ static void traffic_read (void)
        ios = sg_get_network_io_stats (&num);
 
        for (i = 0; i < num; i++)
-               bytes_submit (ios[i].interface_name, ios[i].rx, ios[i].tx);
+               if_submit (ios[i].interface_name, "if_octets", ios[i].rx, ios[i].tx);
 #endif /* HAVE_LIBSTATGRAB */
-}
-#else
-#define traffic_read NULL
+
+       return (0);
+} /* int traffic_read */
 #endif /* TRAFFIC_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, traffic_init, traffic_read, bytes_write);
-       plugin_register ("if_packets", NULL, NULL, packets_write);
-       plugin_register ("if_errors",  NULL, NULL, errors_write);
-       cf_register (MODULE_NAME, traffic_config, config_keys, config_keys_num);
-}
+       plugin_register_data_set (&octets_ds);
+       plugin_register_data_set (&packets_ds);
+       plugin_register_data_set (&errors_ds);
+
+       plugin_register_config ("interface", interface_config,
+                       config_keys, config_keys_num);
 
-#undef BUFSIZE
-#undef MODULE_NAME
+#if HAVE_LIBKSTAT
+       plugin_register_init ("interface", traffic_init);
+#endif
+
+#if TRAFFIC_HAVE_READ
+       plugin_register_read ("interface", traffic_read);
+#endif
+}
diff --git a/src/unixsock.c b/src/unixsock.c
new file mode 100644 (file)
index 0000000..0008b22
--- /dev/null
@@ -0,0 +1,694 @@
+/**
+ * collectd - src/unixsock.c
+ * Copyright (C) 2007  Florian octo Forster
+ *
+ * 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; only version 2 of the License is applicable.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Author:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_debug.h"
+
+/* Folks without pthread will need to disable this plugin. */
+#include <pthread.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+
+#include <grp.h>
+
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX sizeof (((struct sockaddr_un *)0)->sun_path)
+#endif
+
+#define US_DEFAULT_PATH PREFIX"/var/run/"PACKAGE_NAME"-unixsock"
+
+/*
+ * Private data structures
+ */
+/* linked list of cached values */
+typedef struct value_cache_s
+{
+       char       name[4*DATA_MAX_NAME_LEN];
+       int        values_num;
+       gauge_t   *gauge;
+       counter_t *counter;
+       const data_set_t *ds;
+       time_t     time;
+       struct value_cache_s *next;
+} value_cache_t;
+
+/*
+ * Private variables
+ */
+/* valid configuration file keys */
+static const char *config_keys[] =
+{
+       "SocketFile",
+       "SocketGroup",
+       "SocketPerms",
+       NULL
+};
+static int config_keys_num = 3;
+
+/* socket configuration */
+static int   sock_fd    = -1;
+static char *sock_file  = NULL;
+static char *sock_group = NULL;
+static int   sock_perms = S_IRWXU | S_IRWXG;
+
+static pthread_t listen_thread = (pthread_t) 0;
+
+/* Linked list and auxilliary variables for saving values */
+static value_cache_t   *cache_head = NULL;
+static pthread_mutex_t  cache_lock = PTHREAD_MUTEX_INITIALIZER;
+static unsigned int     cache_oldest = UINT_MAX;
+
+/*
+ * Functions
+ */
+static value_cache_t *cache_search (const char *name)
+{
+       value_cache_t *vc;
+
+       for (vc = cache_head; vc != NULL; vc = vc->next)
+       {
+               if (strcmp (vc->name, name) == 0)
+                       break;
+       } /* for vc = cache_head .. NULL */
+
+       return (vc);
+} /* value_cache_t *cache_search */
+
+static int cache_alloc_name (char *ret, int ret_len,
+               const char *hostname,
+               const char *plugin, const char *plugin_instance,
+               const char *type, const char *type_instance)
+{
+       int  status;
+
+       assert (plugin != NULL);
+       assert (type != NULL);
+
+       if ((plugin_instance == NULL) || (strlen (plugin_instance) == 0))
+       {
+               if ((type_instance == NULL) || (strlen (type_instance) == 0))
+                       status = snprintf (ret, ret_len, "%s/%s/%s",
+                                       hostname, plugin, type);
+               else
+                       status = snprintf (ret, ret_len, "%s/%s/%s-%s",
+                                       hostname, plugin, type, type_instance);
+       }
+       else
+       {
+               if ((type_instance == NULL) || (strlen (type_instance) == 0))
+                       status = snprintf (ret, ret_len, "%s/%s-%s/%s",
+                                       hostname, plugin, plugin_instance, type);
+               else
+                       status = snprintf (ret, ret_len, "%s/%s-%s/%s-%s",
+                                       hostname, plugin, plugin_instance, type, type_instance);
+       }
+
+       if ((status < 1) || (status >= ret_len))
+               return (-1);
+       return (0);
+} /* int cache_alloc_name */
+
+static int cache_insert (const data_set_t *ds, const value_list_t *vl)
+{
+       /* We're called from `cache_update' so we don't need to lock the mutex */
+       value_cache_t *vc;
+       int i;
+
+       DBG ("ds->ds_num = %i; vl->values_len = %i;",
+                       ds->ds_num, vl->values_len);
+       assert (ds->ds_num == vl->values_len);
+
+       vc = (value_cache_t *) malloc (sizeof (value_cache_t));
+       if (vc == NULL)
+       {
+               pthread_mutex_unlock (&cache_lock);
+               syslog (LOG_ERR, "unixsock plugin: malloc failed: %s",
+                               strerror (errno));
+               return (-1);
+       }
+
+       vc->gauge = (gauge_t *) malloc (sizeof (gauge_t) * vl->values_len);
+       if (vc->gauge == NULL)
+       {
+               pthread_mutex_unlock (&cache_lock);
+               syslog (LOG_ERR, "unixsock plugin: malloc failed: %s",
+                               strerror (errno));
+               free (vc);
+               return (-1);
+       }
+
+       vc->counter = (counter_t *) malloc (sizeof (counter_t) * vl->values_len);
+       if (vc->counter == NULL)
+       {
+               pthread_mutex_unlock (&cache_lock);
+               syslog (LOG_ERR, "unixsock plugin: malloc failed: %s",
+                               strerror (errno));
+               free (vc->gauge);
+               free (vc);
+               return (-1);
+       }
+
+       if (cache_alloc_name (vc->name, sizeof (vc->name),
+                               vl->host, vl->plugin, vl->plugin_instance,
+                               ds->type, vl->type_instance) != 0)
+       {
+               pthread_mutex_unlock (&cache_lock);
+               syslog (LOG_ERR, "unixsock plugin: cache_alloc_name failed.");
+               free (vc->counter);
+               free (vc->gauge);
+               free (vc);
+               return (-1);
+       }
+
+       for (i = 0; i < ds->ds_num; i++)
+       {
+               if (ds->ds[i].type == DS_TYPE_COUNTER)
+               {
+                       vc->gauge[i] = 0.0;
+                       vc->counter[i] = vl->values[i].counter;
+               }
+               else if (ds->ds[i].type == DS_TYPE_GAUGE)
+               {
+                       vc->gauge[i] = vl->values[i].gauge;
+                       vc->counter[i] = 0;
+               }
+               else
+               {
+                       vc->gauge[i] = 0.0;
+                       vc->counter[i] = 0;
+               }
+       }
+       vc->values_num = ds->ds_num;
+       vc->ds = ds;
+
+       vc->next = cache_head;
+       cache_head = vc;
+
+       vc->time = vl->time;
+       if (vc->time < cache_oldest)
+               cache_oldest = vc->time;
+
+       pthread_mutex_unlock (&cache_lock);
+       return (0);
+} /* int cache_insert */
+
+static int cache_update (const data_set_t *ds, const value_list_t *vl)
+{
+       char name[4*DATA_MAX_NAME_LEN];;
+       value_cache_t *vc;
+       int i;
+
+       if (cache_alloc_name (name, sizeof (name),
+                               vl->host,
+                               vl->plugin, vl->plugin_instance,
+                               ds->type, vl->type_instance) != 0)
+               return (-1);
+
+       pthread_mutex_lock (&cache_lock);
+
+       vc = cache_search (name);
+
+       if (vc == NULL)
+               return (cache_insert (ds, vl));
+
+       assert (vc->values_num == ds->ds_num);
+       assert (vc->values_num == vl->values_len);
+
+       /*
+        * Update the values. This is possibly a lot more that you'd expect
+        * because we honor min and max values and handle counter overflows here.
+        */
+       for (i = 0; i < ds->ds_num; i++)
+       {
+               if (ds->ds[i].type == DS_TYPE_COUNTER)
+               {
+                       if (vl->values[i].counter < vc->counter[i])
+                       {
+                               if (vl->values[i].counter <= 4294967295U)
+                               {
+                                       vc->gauge[i] = ((4294967295U - vl->values[i].counter)
+                                                       + vc->counter[i]) / (vl->time - vc->time);
+                               }
+                               else
+                               {
+                                       vc->gauge[i] = ((18446744073709551615ULL - vl->values[i].counter)
+                                               + vc->counter[i]) / (vl->time - vc->time);
+                               }
+                       }
+                       else
+                       {
+                               vc->gauge[i] = (vl->values[i].counter - vc->counter[i])
+                                       / (vl->time - vc->time);
+                       }
+
+                       vc->counter[i] = vl->values[i].counter;
+               }
+               else if (ds->ds[i].type == DS_TYPE_GAUGE)
+               {
+                       vc->gauge[i] = vl->values[i].gauge;
+                       vc->counter[i] = 0;
+               }
+               else
+               {
+                       vc->gauge[i] = NAN;
+                       vc->counter[i] = 0;
+               }
+
+               if (isnan (vc->gauge[i])
+                               || (!isnan (ds->ds[i].min) && (vc->gauge[i] < ds->ds[i].min))
+                               || (!isnan (ds->ds[i].max) && (vc->gauge[i] > ds->ds[i].max)))
+                       vc->gauge[i] = NAN;
+       } /* for i = 0 .. ds->ds_num */
+
+       vc->ds = ds;
+       vc->time = vl->time;
+
+       if (vc->time < cache_oldest)
+               cache_oldest = vc->time;
+
+       pthread_mutex_unlock (&cache_lock);
+       return (0);
+} /* int cache_update */
+
+static void cache_flush (int max_age)
+{
+       value_cache_t *this;
+       value_cache_t *prev;
+       time_t now;
+
+       pthread_mutex_lock (&cache_lock);
+
+       now = time (NULL);
+
+       if ((now - cache_oldest) <= max_age)
+       {
+               pthread_mutex_unlock (&cache_lock);
+               return;
+       }
+       
+       cache_oldest = now;
+
+       prev = NULL;
+       this = cache_head;
+
+       while (this != NULL)
+       {
+               if ((now - this->time) <= max_age)
+               {
+                       if (this->time < cache_oldest)
+                               cache_oldest = this->time;
+
+                       prev = this;
+                       this = this->next;
+                       continue;
+               }
+
+               if (prev == NULL)
+                       cache_head = this->next;
+               else
+                       prev->next = this->next;
+
+               free (this->gauge);
+               free (this->counter);
+               free (this);
+
+               if (prev == NULL)
+                       this = cache_head;
+               else
+                       this = prev->next;
+       } /* while (this != NULL) */
+
+       pthread_mutex_unlock (&cache_lock);
+} /* int cache_flush */
+
+static int us_open_socket (void)
+{
+       struct sockaddr_un sa;
+       int status;
+
+       sock_fd = socket (PF_UNIX, SOCK_STREAM, 0);
+       if (sock_fd < 0)
+       {
+               syslog (LOG_ERR, "unixsock plugin: socket failed: %s",
+                               strerror (errno));
+               return (-1);
+       }
+
+       memset (&sa, '\0', sizeof (sa));
+       sa.sun_family = AF_UNIX;
+       strncpy (sa.sun_path, (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+                       sizeof (sa.sun_path) - 1);
+       /* unlink (sa.sun_path); */
+
+       status = bind (sock_fd, (struct sockaddr *) &sa, sizeof (sa));
+       if (status != 0)
+       {
+               DBG ("bind failed: %s; sa.sun_path = %s",
+                               strerror (errno), sa.sun_path);
+               syslog (LOG_ERR, "unixsock plugin: bind failed: %s",
+                               strerror (errno));
+               close (sock_fd);
+               sock_fd = -1;
+               return (-1);
+       }
+
+       status = listen (sock_fd, 8);
+       if (status != 0)
+       {
+               syslog (LOG_ERR, "unixsock plugin: listen failed: %s",
+                               strerror (errno));
+               close (sock_fd);
+               sock_fd = -1;
+               return (-1);
+       }
+
+       do
+       {
+               char *grpname;
+               struct group *g;
+               struct group sg;
+               char grbuf[2048];
+
+               grpname = (sock_group != NULL) ? sock_group : COLLECTD_GRP_NAME;
+               g = NULL;
+
+               status = getgrnam_r (grpname, &sg, grbuf, sizeof (grbuf), &g);
+               if (status != 0)
+               {
+                       syslog (LOG_WARNING, "unixsock plugin: getgrnam_r (%s) failed: %s",
+                                       grpname, strerror (status));
+                       break;
+               }
+               if (g == NULL)
+               {
+                       syslog (LOG_WARNING, "unixsock plugin: No such group: `%s'",
+                                       grpname);
+                       break;
+               }
+
+               if (chown ((sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+                                       (uid_t) -1, g->gr_gid) != 0)
+               {
+                       syslog (LOG_WARNING, "unixsock plugin: chown (%s, -1, %i) failed: %s",
+                                       (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+                                       (int) g->gr_gid,
+                                       strerror (errno));
+               }
+       } while (0);
+
+       return (0);
+} /* int us_open_socket */
+
+static int us_handle_getval (FILE *fh, char **fields, int fields_num)
+{
+       char *hostname = fields[1];
+       char *plugin;
+       char *plugin_instance;
+       char *type;
+       char *type_instance;
+       char  name[4*DATA_MAX_NAME_LEN];
+       value_cache_t *vc;
+       int   status;
+       int   i;
+
+       if (fields_num != 2)
+               return (-1);
+
+       plugin = strchr (hostname, '/');
+       if (plugin == NULL)
+               return (-1);
+       *plugin = '\0'; plugin++;
+
+       type = strchr (plugin, '/');
+       if (type == NULL)
+               return (-1);
+       *type = '\0'; type++;
+
+       plugin_instance = strchr (plugin, '-');
+       if (plugin_instance != NULL)
+       {
+               *plugin_instance = '\0';
+               plugin_instance++;
+       }
+
+       type_instance = strchr (type, '-');
+       if (type_instance != NULL)
+       {
+               *type_instance = '\0';
+               type_instance++;
+       }
+
+       status = cache_alloc_name (name, sizeof (name),
+                       hostname, plugin, plugin_instance, type, type_instance);
+       if (status != 0)
+               return (-1);
+
+       pthread_mutex_lock (&cache_lock);
+
+       DBG ("vc = cache_search (%s)", name);
+       vc = cache_search (name);
+
+       if (vc == NULL)
+       {
+               DBG ("Did not find cache entry.");
+               fprintf (fh, "-1 No such value");
+       }
+       else
+       {
+               DBG ("Found cache entry.");
+               fprintf (fh, "%i", vc->values_num);
+               for (i = 0; i < vc->values_num; i++)
+               {
+                       fprintf (fh, " %s=", vc->ds->ds[i].name);
+                       if (isnan (vc->gauge[i]))
+                               fprintf (fh, "NaN");
+                       else
+                               fprintf (fh, "%12e", vc->gauge[i]);
+               }
+       }
+
+       /* Free the mutex as soon as possible and definitely before flushing */
+       pthread_mutex_unlock (&cache_lock);
+
+       fprintf (fh, "\n");
+       fflush (fh);
+
+       return (0);
+} /* int us_handle_getval */
+
+static void *us_handle_client (void *arg)
+{
+       int fd;
+       FILE *fh;
+       char buffer[1024];
+       char *fields[128];
+       int   fields_num;
+
+       fd = *((int *) arg);
+       free (arg);
+       arg = NULL;
+
+       DBG ("Reading from fd #%i", fd);
+
+       fh = fdopen (fd, "r+");
+       if (fh == NULL)
+       {
+               syslog (LOG_ERR, "unixsock plugin: fdopen failed: %s",
+                               strerror (errno));
+               close (fd);
+               pthread_exit ((void *) 1);
+       }
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               int len;
+
+               len = strlen (buffer);
+               while ((len > 0)
+                               && ((buffer[len - 1] == '\n') || (buffer[len - 1] == '\r')))
+                       buffer[--len] = '\0';
+
+               if (len == 0)
+                       continue;
+
+               DBG ("fgets -> buffer = %s; len = %i;", buffer, len);
+
+               fields_num = strsplit (buffer, fields,
+                               sizeof (fields) / sizeof (fields[0]));
+
+               if (fields_num < 1)
+               {
+                       close (fd);
+                       break;
+               }
+
+               if (strcasecmp (fields[0], "getval") == 0)
+               {
+                       us_handle_getval (fh, fields, fields_num);
+               }
+               else
+               {
+                       fprintf (fh, "Unknown command: %s\n", fields[0]);
+                       fflush (fh);
+               }
+       } /* while (fgets) */
+
+       DBG ("Exiting..");
+       close (fd);
+
+       pthread_exit ((void *) 0);
+} /* void *us_handle_client */
+
+static void *us_server_thread (void *arg)
+{
+       int  status;
+       int *remote_fd;
+       pthread_t th;
+       pthread_attr_t th_attr;
+
+       if (us_open_socket () != 0)
+               pthread_exit ((void *) 1);
+
+       while (42)
+       {
+               DBG ("Calling accept..");
+               status = accept (sock_fd, NULL, NULL);
+               if (status < 0)
+               {
+                       if (errno == EINTR)
+                               continue;
+
+                       syslog (LOG_ERR, "unixsock plugin: accept failed: %s",
+                                       strerror (errno));
+                       close (sock_fd);
+                       sock_fd = -1;
+                       pthread_exit ((void *) 1);
+               }
+
+               remote_fd = (int *) malloc (sizeof (int));
+               if (remote_fd == NULL)
+               {
+                       syslog (LOG_WARNING, "unixsock plugin: malloc failed: %s",
+                                       strerror (errno));
+                       close (status);
+                       continue;
+               }
+               *remote_fd = status;
+
+               DBG ("Spawning child to handle connection on fd #%i", *remote_fd);
+
+               pthread_attr_init (&th_attr);
+               pthread_attr_setdetachstate (&th_attr, PTHREAD_CREATE_DETACHED);
+
+               status = pthread_create (&th, &th_attr, us_handle_client, (void *) remote_fd);
+               if (status != 0)
+               {
+                       syslog (LOG_WARNING, "unixsock plugin: pthread_create failed: %s",
+                                       strerror (status));
+                       close (*remote_fd);
+                       free (remote_fd);
+                       continue;
+               }
+       } /* while (42) */
+
+       return ((void *) 0);
+} /* void *us_server_thread */
+
+static int us_config (const char *key, const char *val)
+{
+       if (strcasecmp (key, "SocketFile") == 0)
+       {
+               sfree (sock_file);
+               sock_file = strdup (val);
+       }
+       else if (strcasecmp (key, "SocketGroup") == 0)
+       {
+               sfree (sock_group);
+               sock_group = strdup (val);
+       }
+       else if (strcasecmp (key, "SocketPerms") == 0)
+       {
+               sock_perms = (int) strtol (val, NULL, 8);
+       }
+       else
+       {
+               return (-1);
+       }
+
+       return (0);
+} /* int us_config */
+
+static int us_init (void)
+{
+       int status;
+
+       status = pthread_create (&listen_thread, NULL, us_server_thread, NULL);
+       if (status != 0)
+       {
+               syslog (LOG_ERR, "unixsock plugin: pthread_create failed: %s",
+                               strerror (status));
+               return (-1);
+       }
+
+       return (0);
+} /* int us_init */
+
+static int us_shutdown (void)
+{
+       void *ret;
+
+       if (listen_thread != (pthread_t) 0)
+       {
+               pthread_kill (listen_thread, SIGTERM);
+               pthread_join (listen_thread, &ret);
+               listen_thread = (pthread_t) 0;
+       }
+
+       plugin_unregister_init ("unixsock");
+       plugin_unregister_write ("unixsock");
+       plugin_unregister_shutdown ("unixsock");
+
+       return (0);
+} /* int us_shutdown */
+
+static int us_write (const data_set_t *ds, const value_list_t *vl)
+{
+       cache_update (ds, vl);
+       cache_flush (2 * atoi (COLLECTD_STEP));
+
+       return (0);
+}
+
+void module_register (void)
+{
+       plugin_register_config ("unixsock", us_config,
+                       config_keys, config_keys_num);
+       plugin_register_init ("unixsock", us_init);
+       plugin_register_write ("unixsock", us_write);
+       plugin_register_shutdown ("unixsock", us_shutdown);
+} /* void module_register (void) */
+
+/* vim: set sw=4 ts=4 sts=4 tw=78 : */
index 973fda0..03d6148 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/users.c
- * Copyright (C) 2005,2006  Sebastian Harl
+ * Copyright (C) 2005-2007  Sebastian Harl
  *
  * 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
 # define USERS_HAVE_READ 0
 #endif
 
-static char *rrd_file = "users.rrd";
-static char *ds_def[] =
+static data_source_t dsrc[1] =
 {
-       "DS:users:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       NULL
+       {"users",  DS_TYPE_GAUGE, 0.0, 65535.0}
 };
-static int ds_num = 1;
 
-static void users_init (void)
+static data_set_t ds =
 {
-       /* we have nothing to do here :-) */
-       return;
-} /* static void users_init(void) */
-
-static void users_write (char *host, char *inst, char *val)
-{
-       rrd_update_file(host, rrd_file, val, ds_def, ds_num);
-       return;
-} /* static void users_write(char *host, char *inst, char *val) */
+       "users", 1, dsrc
+};
 
 #if USERS_HAVE_READ
-/* I don't like this temporary macro definition - well it's used everywhere
-   else in the collectd-sources, so I will just stick with it...  */
-#define BUFSIZE 256
-static void users_submit (unsigned int users)
+static void users_submit (gauge_t value)
 {
-       char buf[BUFSIZE] = "";
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       if (snprintf(buf, BUFSIZE, "%u:%u", 
-               (unsigned int)curtime, users) >= BUFSIZE)
-       {
-               return;
-       }
+       values[0].gauge = value;
 
-       plugin_submit(MODULE_NAME, "-", buf);
-       return;
-} /* static void users_submit(unsigned int users) */
-#undef BUFSIZE
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "users");
+
+       plugin_dispatch_values ("users", &vl);
+} /* void users_submit */
 
-static void users_read (void)
+static int users_read (void)
 {
 #if HAVE_GETUTXENT
        unsigned int users = 0;
@@ -114,17 +102,16 @@ static void users_read (void)
        }
        endutent();
 
-       users_submit(users);
+       users_submit (users);
 #endif /* HAVE_GETUTENT */
 
-       return;
-} /* static void users_read(void) */
-#else
-# define users_read NULL
+       return (0);
+} /* int users_read */
 #endif /* USERS_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, users_init, users_read, users_write);
+       plugin_register_data_set (&ds);
+       plugin_register_read ("users", users_read);
        return;
 } /* void module_register(void) */
diff --git a/src/utils_avltree.c b/src/utils_avltree.c
new file mode 100644 (file)
index 0000000..786bc38
--- /dev/null
@@ -0,0 +1,708 @@
+/**
+ * collectd - src/utils_avltree.c
+ * Copyright (C) 2006,2007  Florian octo Forster
+ *
+ * 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.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "utils_avltree.h"
+
+#define BALANCE(n) ((((n)->left == NULL) ? 0 : (n)->left->height) \
+               - (((n)->right == NULL) ? 0 : (n)->right->height))
+
+/*
+ * private data types
+ */
+struct avl_node_s
+{
+       void *key;
+       void *value;
+
+       int height;
+       struct avl_node_s *left;
+       struct avl_node_s *right;
+       struct avl_node_s *parent;
+};
+typedef struct avl_node_s avl_node_t;
+
+struct avl_tree_s
+{
+       avl_node_t *root;
+       int (*compare) (const void *, const void *);
+};
+
+struct avl_iterator_s
+{
+       avl_tree_t *tree;
+       avl_node_t *node;
+};
+
+/*
+ * private functions
+ */
+#if 0
+static void verify_tree (avl_node_t *n)
+{
+       if (n == NULL)
+               return;
+
+       verify_tree (n->left);
+       verify_tree (n->right);
+
+       assert ((BALANCE (n) >= -1) && (BALANCE (n) <= 1));
+       assert ((n->parent == NULL) || (n->parent->right == n) || (n->parent->left == n));
+} /* void verify_tree */
+#else
+# define verify_tree(n) /**/
+#endif
+
+static void free_node (avl_node_t *n)
+{
+       if (n == NULL)
+               return;
+
+       if (n->left != NULL)
+               free_node (n->left);
+       if (n->right != NULL)
+               free_node (n->right);
+
+       free (n);
+}
+
+static int calc_height (avl_node_t *n)
+{
+       int height_left;
+       int height_right;
+
+       if (n == NULL)
+               return (0);
+
+       height_left  = (n->left == NULL)  ? 0 : n->left->height;
+       height_right = (n->right == NULL) ? 0 : n->right->height;
+
+       return (((height_left > height_right)
+                               ? height_left
+                               : height_right) + 1);
+} /* int calc_height */
+
+static avl_node_t *search (avl_tree_t *t, const void *key)
+{
+       avl_node_t *n;
+       int cmp;
+
+       n = t->root;
+       while (n != NULL)
+       {
+               cmp = t->compare (key, n->key);
+               if (cmp == 0)
+                       return (n);
+               else if (cmp < 0)
+                       n = n->left;
+               else
+                       n = n->right;
+       }
+
+       return (NULL);
+}
+
+/*         (x)             (y)
+ *        /   \           /   \
+ *     (y)    /\         /\    (x)
+ *    /   \  /_c\  ==>  / a\  /   \
+ *   /\   /\           /____\/\   /\
+ *  / a\ /_b\               /_b\ /_c\
+ * /____\
+ */
+static avl_node_t *rotate_right (avl_tree_t *t, avl_node_t *x)
+{
+       avl_node_t *p;
+       avl_node_t *y;
+       avl_node_t *b;
+
+       p = x->parent;
+       y = x->left;
+       b = y->right;
+
+       x->left = b;
+       if (b != NULL)
+               b->parent = x;
+
+       x->parent = y;
+       y->right = x;
+
+       y->parent = p;
+       assert ((p == NULL) || (p->left == x) || (p->right == x));
+       if (p == NULL)
+               t->root = y;
+       else if (p->left == x)
+               p->left = y;
+       else
+               p->right = y;
+
+       x->height = calc_height (x);
+       y->height = calc_height (y);
+
+       return (y);
+} /* void rotate_left */
+
+/*
+ *    (x)                   (y)
+ *   /   \                 /   \
+ *  /\    (y)           (x)    /\
+ * /_a\  /   \   ==>   /   \  / c\
+ *      /\   /\       /\   /\/____\
+ *     /_b\ / c\     /_a\ /_b\
+ *         /____\
+ */
+static avl_node_t *rotate_left (avl_tree_t *t, avl_node_t *x)
+{
+       avl_node_t *p;
+       avl_node_t *y;
+       avl_node_t *b;
+
+       p = x->parent;
+       y = x->right;
+       b = y->left;
+
+       x->right = b;
+       if (b != NULL)
+               b->parent = x;
+
+       x->parent = y;
+       y->left = x;
+
+       y->parent = p;
+       assert ((p == NULL) || (p->left == x) || (p->right == x));
+       if (p == NULL)
+               t->root = y;
+       else if (p->left == x)
+               p->left = y;
+       else
+               p->right = y;
+
+       x->height = calc_height (x);
+       y->height = calc_height (y);
+
+       return (y);
+} /* void rotate_left */
+
+static avl_node_t *rotate_left_right (avl_tree_t *t, avl_node_t *x)
+{
+       rotate_left (t, x->left);
+       return (rotate_right (t, x));
+} /* void rotate_left_right */
+
+static avl_node_t *rotate_right_left (avl_tree_t *t, avl_node_t *x)
+{
+       rotate_right (t, x->right);
+       return (rotate_left (t, x));
+} /* void rotate_right_left */
+
+static void rebalance (avl_tree_t *t, avl_node_t *n)
+{
+       int b_top;
+       int b_bottom;
+
+       while (n != NULL)
+       {
+               b_top = BALANCE (n);
+               assert ((b_top >= -2) && (b_top <= 2));
+
+               if (b_top == -2)
+               {
+                       assert (n->right != NULL);
+                       b_bottom = BALANCE (n->right);
+                       assert ((b_bottom >= -1) || (b_bottom <= 1));
+                       if (b_bottom == 1)
+                               n = rotate_right_left (t, n);
+                       else
+                               n = rotate_left (t, n);
+               }
+               else if (b_top == 2)
+               {
+                       assert (n->left != NULL);
+                       b_bottom = BALANCE (n->left);
+                       assert ((b_bottom >= -1) || (b_bottom <= 1));
+                       if (b_bottom == -1)
+                               n = rotate_left_right (t, n);
+                       else
+                               n = rotate_right (t, n);
+               }
+               else
+               {
+                       int height = calc_height (n);
+                       if (height == n->height)
+                               break;
+                       n->height = height;
+               }
+
+               assert (n->height == calc_height (n));
+
+               n = n->parent;
+       } /* while (n != NULL) */
+} /* void rebalance */
+
+static avl_node_t *avl_node_next (avl_tree_t *t, avl_node_t *n)
+{
+       avl_node_t *r; /* return node */
+
+       if (n == NULL)
+       {
+               return (NULL);
+       }
+
+       /* If we can't descent any further, we have to backtrack to the first
+        * parent that's bigger than we, i. e. who's _left_ child we are. */
+       if (n->right == NULL)
+       {
+               r = n->parent;
+               while ((r != NULL) && (r->parent != NULL))
+               {
+                       if (r->left == n)
+                               break;
+                       n = r;
+                       r = n->parent;
+               }
+
+               /* n->right == NULL && r == NULL => t is root and has no next
+                * r->left != n => r->right = n => r->parent == NULL */
+               if ((r == NULL) || (r->left != n))
+               {
+                       assert ((r == NULL) || (r->parent == NULL));
+                       return (NULL);
+               }
+               else
+               {
+                       assert (r->left == n);
+                       return (r);
+               }
+       }
+       else
+       {
+               r = n->right;
+               while (r->left != NULL)
+                       r = r->left;
+       }
+
+       return (r);
+} /* avl_node_t *avl_node_next */
+
+static avl_node_t *avl_node_prev (avl_tree_t *t, avl_node_t *n)
+{
+       avl_node_t *r; /* return node */
+
+       if (n == NULL)
+       {
+               return (NULL);
+       }
+
+       /* If we can't descent any further, we have to backtrack to the first
+        * parent that's smaller than we, i. e. who's _right_ child we are. */
+       if (n->left == NULL)
+       {
+               r = n->parent;
+               while ((r != NULL) && (r->parent != NULL))
+               {
+                       if (r->right == n)
+                               break;
+                       n = r;
+                       r = n->parent;
+               }
+
+               /* n->left == NULL && r == NULL => t is root and has no next
+                * r->right != n => r->left = n => r->parent == NULL */
+               if ((r == NULL) || (r->right != n))
+               {
+                       assert ((r == NULL) || (r->parent == NULL));
+                       return (NULL);
+               }
+               else
+               {
+                       assert (r->right == n);
+                       return (r);
+               }
+       }
+       else
+       {
+               r = n->left;
+               while (r->right != NULL)
+                       r = r->right;
+       }
+
+       return (r);
+} /* avl_node_t *avl_node_prev */
+
+static int _remove (avl_tree_t *t, avl_node_t *n)
+{
+       assert ((t != NULL) && (n != NULL));
+
+       if ((n->left != NULL) && (n->right != NULL))
+       {
+               avl_node_t *r; /* replacement node */
+               if (BALANCE (n) > 0) /* left subtree is higher */
+               {
+                       assert (n->left != NULL);
+                       r = avl_node_prev (t, n);
+                       
+               }
+               else /* right subtree is higher */
+               {
+                       assert (n->right != NULL);
+                       r = avl_node_next (t, n);
+               }
+
+               assert ((r->left == NULL) || (r->right == NULL));
+
+               /* copy content */
+               n->key   = r->key;
+               n->value = r->value;
+
+               n = r;
+       }
+
+       assert ((n->left == NULL) || (n->right == NULL));
+
+       if ((n->left == NULL) && (n->right == NULL))
+       {
+               /* Deleting a leave is easy */
+               if (n->parent == NULL)
+               {
+                       assert (t->root == n);
+                       t->root = NULL;
+               }
+               else
+               {
+                       assert ((n->parent->left == n)
+                                       || (n->parent->right == n));
+                       if (n->parent->left == n)
+                               n->parent->left = NULL;
+                       else
+                               n->parent->right = NULL;
+
+                       rebalance (t, n->parent);
+               }
+
+               free_node (n);
+       }
+       else if (n->left == NULL)
+       {
+               assert (BALANCE (n) == -1);
+               assert ((n->parent == NULL) || (n->parent->left == n) || (n->parent->right == n));
+               if (n->parent == NULL)
+               {
+                       assert (t->root == n);
+                       t->root = n->right;
+               }
+               else if (n->parent->left == n)
+               {
+                       n->parent->left = n->right;
+               }
+               else
+               {
+                       n->parent->right = n->right;
+               }
+               n->right->parent = n->parent;
+
+               if (n->parent != NULL)
+                       rebalance (t, n->parent);
+
+               n->right = NULL;
+               free_node (n);
+       }
+       else if (n->right == NULL)
+       {
+               assert (BALANCE (n) == 1);
+               assert ((n->parent == NULL) || (n->parent->left == n) || (n->parent->right == n));
+               if (n->parent == NULL)
+               {
+                       assert (t->root == n);
+                       t->root = n->left;
+               }
+               else if (n->parent->left == n)
+               {
+                       n->parent->left = n->left;
+               }
+               else
+               {
+                       n->parent->right = n->left;
+               }
+               n->left->parent = n->parent;
+
+               if (n->parent != NULL)
+                       rebalance (t, n->parent);
+
+               n->left = NULL;
+               free_node (n);
+       }
+       else
+       {
+               assert (0);
+       }
+
+       return (0);
+} /* void *_remove */
+
+/*
+ * public functions
+ */
+avl_tree_t *avl_create (int (*compare) (const void *, const void *))
+{
+       avl_tree_t *t;
+
+       if (compare == NULL)
+               return (NULL);
+
+       if ((t = (avl_tree_t *) malloc (sizeof (avl_tree_t))) == NULL)
+               return (NULL);
+
+       t->root = NULL;
+       t->compare = compare;
+
+       return (t);
+}
+
+void avl_destroy (avl_tree_t *t)
+{
+       free_node (t->root);
+       free (t);
+}
+
+int avl_insert (avl_tree_t *t, void *key, void *value)
+{
+       avl_node_t *new;
+       avl_node_t *nptr;
+       int cmp;
+
+       if ((new = (avl_node_t *) malloc (sizeof (avl_node_t))) == NULL)
+               return (-1);
+
+       new->key = key;
+       new->value = value;
+       new->height = 1;
+       new->left = NULL;
+       new->right = NULL;
+
+       if (t->root == NULL)
+       {
+               new->parent = NULL;
+               t->root = new;
+               return (0);
+       }
+
+       nptr = t->root;
+       while (42)
+       {
+               cmp = t->compare (nptr->key, new->key);
+               if (cmp == 0)
+               {
+                       free_node (new);
+                       return (-1);
+               }
+               else if (cmp < 0)
+               {
+                       /* nptr < new */
+                       if (nptr->right == NULL)
+                       {
+                               nptr->right = new;
+                               new->parent = nptr;
+                               rebalance (t, nptr);
+                               break;
+                       }
+                       else
+                       {
+                               nptr = nptr->right;
+                       }
+               }
+               else /* if (cmp > 0) */
+               {
+                       /* nptr > new */
+                       if (nptr->left == NULL)
+                       {
+                               nptr->left = new;
+                               new->parent = nptr;
+                               rebalance (t, nptr);
+                               break;
+                       }
+                       else
+                       {
+                               nptr = nptr->left;
+                       }
+               }
+       } /* while (42) */
+
+       verify_tree (t->root);
+       return (0);
+} /* int avl_insert */
+
+int avl_remove (avl_tree_t *t, const void *key, void **rkey, void **rvalue)
+{
+       avl_node_t *n;
+       int status;
+
+       assert (t != NULL);
+
+       n = search (t, key);
+       if (n == NULL)
+               return (-1);
+
+       if (rkey != NULL)
+               *rkey = n->key;
+       if (rvalue != NULL)
+               *rvalue = n->value;
+
+       status = _remove (t, n);
+       verify_tree (t->root);
+       return (status);
+} /* void *avl_remove */
+
+int avl_get (avl_tree_t *t, const void *key, void **value)
+{
+       avl_node_t *n;
+
+       assert (value != NULL);
+
+       n = search (t, key);
+       if (n == NULL)
+               return (-1);
+
+       *value = n->value;
+
+       return (0);
+}
+
+int avl_pick (avl_tree_t *t, void **key, void **value)
+{
+       avl_node_t *n;
+       avl_node_t *p;
+
+       if ((key == NULL) || (value == NULL))
+               return (-1);
+       if (t->root == NULL)
+               return (-1);
+
+       n = t->root;
+       while ((n->left != NULL) || (n->right != NULL))
+       {
+               int height_left  = (n->left  == NULL) ? 0 : n->left->height;
+               int height_right = (n->right == NULL) ? 0 : n->right->height;
+
+               if (height_left > height_right)
+                       n = n->left;
+               else
+                       n = n->right;
+       }
+
+       p = n->parent;
+       if (p == NULL)
+               t->root = NULL;
+       else if (p->left == n)
+               p->left = NULL;
+       else
+               p->right = NULL;
+
+       *key   = n->key;
+       *value = n->value;
+
+       free_node (n);
+       rebalance (t, p);
+
+       return (0);
+} /* int avl_pick */
+
+avl_iterator_t *avl_get_iterator (avl_tree_t *t)
+{
+       avl_iterator_t *iter;
+
+       if (t == NULL)
+               return (NULL);
+
+       iter = (avl_iterator_t *) malloc (sizeof (avl_iterator_t));
+       if (iter == NULL)
+               return (NULL);
+       memset (iter, '\0', sizeof (avl_iterator_t));
+       iter->tree = t;
+
+       return (iter);
+} /* avl_iterator_t *avl_get_iterator */
+
+int avl_iterator_next (avl_iterator_t *iter, void **key, void **value)
+{
+       avl_node_t *n;
+
+       if ((iter == NULL) || (key == NULL) || (value == NULL))
+               return (-1);
+
+       if (iter->node == NULL)
+       {
+               for (n = iter->tree->root; n != NULL; n = n->left)
+                       if (n->left == NULL)
+                               break;
+               iter->node = n;
+       }
+       else
+       {
+               n = avl_node_next (iter->tree, iter->node);
+       }
+
+       if (n == NULL)
+               return (-1);
+
+       iter->node = n;
+       *key = n->key;
+       *value = n->value;
+
+       return (0);
+} /* int avl_iterator_next */
+
+int avl_iterator_prev (avl_iterator_t *iter, void **key, void **value)
+{
+       avl_node_t *n;
+
+       if ((iter == NULL) || (key == NULL) || (value == NULL))
+               return (-1);
+
+       if (iter->node == NULL)
+       {
+               for (n = iter->tree->root; n != NULL; n = n->left)
+                       if (n->right == NULL)
+                               break;
+               iter->node = n;
+       }
+       else
+       {
+               n = avl_node_prev (iter->tree, iter->node);
+       }
+
+       if (n == NULL)
+               return (-1);
+
+       iter->node = n;
+       *key = n->key;
+       *value = n->value;
+
+       return (0);
+} /* int avl_iterator_prev */
+
+void avl_iterator_destroy (avl_iterator_t *iter)
+{
+       free (iter);
+}
diff --git a/src/utils_avltree.h b/src/utils_avltree.h
new file mode 100644 (file)
index 0000000..0ac6087
--- /dev/null
@@ -0,0 +1,144 @@
+/**
+ * collectd - src/utils_avltree.h
+ * Copyright (C) 2006,2007  Florian octo Forster
+ *
+ * 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.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#ifndef UTILS_AVLTREE_H
+#define UTILS_AVLTREE_H 1
+
+struct avl_tree_s;
+typedef struct avl_tree_s avl_tree_t;
+
+struct avl_iterator_s;
+typedef struct avl_iterator_s avl_iterator_t;
+
+/*
+ * NAME
+ *   avl_create
+ *
+ * DESCRIPTION
+ *   Allocates a new AVL-tree.
+ *
+ * PARAMETERS
+ *   `compare'  The function-pointer `compare' is used to compare two keys. It
+ *              has to return less than zero if it's first argument is smaller
+ *              then the second argument, more than zero if the first argument
+ *              is bigger than the second argument and zero if they are equal.
+ *              If your keys are char-pointers, you can use the `strcmp'
+ *              function from the libc here.
+ *
+ * RETURN VALUE
+ *   A avl_tree_t-pointer upon success or NULL upon failure.
+ */
+avl_tree_t *avl_create (int (*compare) (const void *, const void *));
+
+
+/*
+ * NAME
+ *   avl_destroy
+ *
+ * DESCRIPTION
+ *   Deallocates an AVL-tree. Stored value- and key-pointer are lost, but of
+ *   course not freed.
+ */
+void avl_destroy (avl_tree_t *t);
+
+/*
+ * NAME
+ *   avl_insert
+ *
+ * DESCRIPTION
+ *   Stores the key-value-pair in the AVL-tree pointed to by `t'.
+ *
+ * PARAMETERS
+ *   `t'        AVL-tree to store the data in.
+ *   `key'      Key used to store the value under. This is used to get back to
+ *              the value again.
+ *   `value'    Value to be stored.
+ *
+ * RETURN VALUE
+ *   Zero upon success and non-zero upon failure and if the key is already
+ *   stored in the tree.
+ */
+int avl_insert (avl_tree_t *t, void *key, void *value);
+
+/*
+ * NAME
+ *   avl_remove
+ *
+ * DESCRIPTION
+ *   Removes a key-value-pair from the tree t. The stored key and value may be
+ *   returned in `rkey' and `rvalue'.
+ *
+ * PARAMETERS
+ *   `t'       AVL-tree to remove key-value-pair from.
+ *   `key'      Key to identify the entry.
+ *   `rkey'     Pointer to a pointer in which to store the key. May be NULL.
+ *   `rvalue'   Pointer to a pointer in which to store the value. May be NULL.
+ *
+ * RETURN VALUE
+ *   Zero upon success or non-zero if the key isn't found in the tree.
+ */
+int avl_remove (avl_tree_t *t, const void *key, void **rkey, void **rvalue);
+
+/*
+ * NAME
+ *   avl_get
+ *
+ * DESCRIPTION
+ *   Retrieve the `value' belonging to `key'.
+ *
+ * PARAMETERS
+ *   `t'       AVL-tree to get the value from.
+ *   `key'      Key to identify the entry.
+ *   `value'    Pointer to a pointer in which to store the value. May be NULL.
+ *
+ * RETURN VALUE
+ *   Zero upon success or non-zero if the key isn't found in the tree.
+ */
+int avl_get (avl_tree_t *t, const void *key, void **value);
+
+/*
+ * NAME
+ *   avl_pick
+ *
+ * DESCRIPTION
+ *   Remove a (pseudo-)random element from the tree and return it's `key' and
+ *   `value'. Entries are not returned in any particular order. This function
+ *   is intended for cache-flushes that don't care about the order but simply
+ *   want to remove all elements, one at a time.
+ *
+ * PARAMETERS
+ *   `t'       AVL-tree to get the value from.
+ *   `key'      Pointer to a pointer in which to store the key.
+ *   `value'    Pointer to a pointer in which to store the value.
+ *
+ * RETURN VALUE
+ *   Zero upon success or non-zero if the tree is empty or key or value is
+ *   NULL.
+ */
+int avl_pick (avl_tree_t *t, void **key, void **value);
+
+avl_iterator_t *avl_get_iterator (avl_tree_t *t);
+int avl_iterator_next (avl_iterator_t *iter, void **key, void **value);
+int avl_iterator_prev (avl_iterator_t *iter, void **key, void **value);
+void avl_iterator_destroy (avl_iterator_t *iter);
+
+#endif /* UTILS_AVLTREE_H */
diff --git a/src/utils_llist.c b/src/utils_llist.c
new file mode 100644 (file)
index 0000000..a815035
--- /dev/null
@@ -0,0 +1,148 @@
+/**
+ * collectd - src/utils_llist.c
+ * Copyright (C) 2006 Florian Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; only
+ * version 2 of the Licence is applicable.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Authors:
+ *   Florian Forster <octo at verplant.org>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils_llist.h"
+
+/*
+ * Private data types
+ */
+struct llist_s
+{
+       llentry_t *head;
+       llentry_t *tail;
+};
+
+/*
+ * Public functions
+ */
+llist_t *llist_create (void)
+{
+       llist_t *ret;
+
+       ret = (llist_t *) malloc (sizeof (llist_t));
+       if (ret == NULL)
+               return (NULL);
+
+       memset (ret, '\0', sizeof (llist_t));
+
+       return (ret);
+}
+
+void llist_destroy (llist_t *l)
+{
+       llentry_t *e_this;
+       llentry_t *e_next;
+
+       for (e_this = l->head; e_this != NULL; e_this = e_next)
+       {
+               e_next = e_this->next;
+               llentry_destroy (e_this);
+       }
+
+       free (l);
+}
+
+llentry_t *llentry_create (const char *key, void *value)
+{
+       llentry_t *e;
+
+       e = (llentry_t *) malloc (sizeof (llentry_t));
+       if (e == NULL)
+               return (NULL);
+
+       e->key   = strdup (key);
+       e->value = value;
+       e->next  = NULL;
+
+       if (e->key == NULL)
+       {
+               free (e);
+               return (NULL);
+       }
+
+       return (e);
+}
+
+void llentry_destroy (llentry_t *e)
+{
+       free (e->key);
+       free (e);
+}
+
+void llist_append (llist_t *l, llentry_t *e)
+{
+       e->next = NULL;
+
+       if (l->tail == NULL)
+               l->head = e;
+       else
+               l->tail->next = e;
+
+       l->tail = e;
+}
+
+void llist_prepend (llist_t *l, llentry_t *e)
+{
+       e->next = l->head;
+       l->head = e;
+}
+
+void llist_remove (llist_t *l, llentry_t *e)
+{
+       llentry_t *prev;
+
+       prev = l->head;
+       while ((prev != NULL) && (prev->next != e))
+               prev = prev->next;
+
+       if (prev != NULL)
+               prev->next = e->next;
+       if (l->head == e)
+               l->head = e->next;
+       if (l->tail == e)
+               l->tail = prev;
+}
+
+llentry_t *llist_search (llist_t *l, const char *key)
+{
+       llentry_t *e;
+
+       for (e = l->head; e != NULL; e = e->next)
+               if (strcmp (key, e->key) == 0)
+                       break;
+
+       return (e);
+}
+
+llentry_t *llist_head (llist_t *l)
+{
+       return (l->head);
+}
+
+llentry_t *llist_tail (llist_t *l)
+{
+       return (l->tail);
+}
diff --git a/src/utils_llist.h b/src/utils_llist.h
new file mode 100644 (file)
index 0000000..603fc87
--- /dev/null
@@ -0,0 +1,59 @@
+/**
+ * collectd - src/utils_llist.h
+ * Copyright (C) 2006 Florian Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; only
+ * version 2 of the Licence is applicable.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Authors:
+ *   Florian Forster <octo at verplant.org>
+ */
+
+#ifndef UTILS_LLIST_H
+#define UTILS_LLIST_H 1
+
+/*
+ * Data types
+ */
+struct llentry_s
+{
+       char *key;
+       void *value;
+       struct llentry_s *next;
+};
+typedef struct llentry_s llentry_t;
+
+struct llist_s;
+typedef struct llist_s llist_t;
+
+/*
+ * Functions
+ */
+llist_t *llist_create (void);
+void llist_destroy (llist_t *l);
+
+llentry_t *llentry_create (const char *key, void *value);
+void llentry_destroy (llentry_t *e);
+
+void llist_append (llist_t *l, llentry_t *e);
+void llist_prepend (llist_t *l, llentry_t *e);
+void llist_remove (llist_t *l, llentry_t *e);
+
+llentry_t *llist_search (llist_t *l, const char *key);
+
+llentry_t *llist_head (llist_t *l);
+llentry_t *llist_tail (llist_t *l);
+
+#endif /* UTILS_LLIST_H */
index 3a77961..00a1e6a 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/vserver.c
- * Copyright (C) 2006  Sebastian Harl
+ * Copyright (C) 2006,2007  Sebastian Harl
  *
  * 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
 # define VSERVER_HAVE_READ 0
 #endif /* defined(KERNEL_LINUX) */
 
-static char *rrd_unix  = "vserver-%s/traffic-unix.rrd";
-static char *rrd_inet  = "vserver-%s/traffic-inet.rrd";
-static char *rrd_inet6 = "vserver-%s/traffic-inet6.rrd";
-static char *rrd_other = "vserver-%s/traffic-other.rrd";
-static char *rrd_unspec        = "vserver-%s/traffic-unspec.rrd";
-
-static char *rrd_thread        = "vserver-%s/vs_threads.rrd";
-
-static char *rrd_load  = "vserver-%s/load.rrd";
-
-static char *rrd_procs = "vserver-%s/vs_processes.rrd";
-static char *rrd_memory        = "vserver-%s/vs_memory.rrd";
+static data_source_t octets_dsrc[2] =
+{
+       {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+       {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
 
-/* 9223372036854775807 == LLONG_MAX */
-/* bytes transferred */
-static char *ds_def_unix[] =
+static data_set_t octets_ds =
 {
-       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       NULL
+       "if_octets", 2, octets_dsrc
 };
-static int ds_num_unix = 3;
 
-static char *ds_def_inet[] =
+static data_source_t load_dsrc[3] =
 {
-       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       NULL
+       {"shortterm", DS_TYPE_GAUGE, 0.0, 100.0},
+       {"midterm",   DS_TYPE_GAUGE, 0.0, 100.0},
+       {"longterm",  DS_TYPE_GAUGE, 0.0, 100.0}
 };
-static int ds_num_inet = 3;
 
-static char *ds_def_inet6[] =
+static data_set_t load_ds =
 {
-       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       NULL
+       "load", 3, load_dsrc
 };
-static int ds_num_inet6 = 3;
 
-static char *ds_def_other[] =
+static data_source_t threads_dsrc[1] =
 {
-       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       NULL
+       {"value", DS_TYPE_GAUGE, 0.0, 65535.0}
 };
-static int ds_num_other = 3;
 
-static char *ds_def_unspec[] =
+static data_set_t threads_ds =
 {
-       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       NULL
+       "vs_threads", 1, threads_dsrc
 };
-static int ds_num_unspec = 3;
 
-static char *ds_def_threads[] =
+static data_source_t processes_dsrc[1] =
 {
-       "DS:total:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       "DS:uninterruptible:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       "DS:onhold:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       NULL
+       {"value", DS_TYPE_GAUGE, 0.0, 65535.0}
 };
-static int ds_num_threads = 4;
 
-static char *ds_def_load[] =
+static data_set_t processes_ds =
 {
-       "DS:shortterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
-       "DS:midterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
-       "DS:longterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
-       NULL
+       "vs_processes", 1, processes_dsrc
 };
-static int ds_num_load = 3;
 
-static char *ds_def_procs[] =
+static data_source_t memory_dsrc[1] =
 {
-       "DS:total:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
-       NULL
+       {"value", DS_TYPE_GAUGE, 0.0, 9223372036854775807.0}
 };
-static int ds_num_procs = 1;
 
-/* 9223372036854775807 == LLONG_MAX */
-/* bytes */
-static char *ds_def_memory[] =
+static data_set_t memory_ds =
 {
-       "DS:vm:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:vml:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:rss:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       "DS:anon:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
-       NULL
+       "vs_memory", 1, memory_dsrc
 };
-static int ds_num_memory = 4;
 
+#if VSERVER_HAVE_READ
 static int pagesize = 0;
 
-static void vserver_init (void)
+static int vserver_init (void)
 {
        /* XXX Should we check for getpagesize () in configure?
         * What's the right thing to do, if there is no getpagesize ()? */
        pagesize = getpagesize ();
-       return;
-} /* static void vserver_init(void) */
-
-static void vserver_unix_write (char *host, char *inst, char *val)
-{
-       int  len;
-       char filename[BUFSIZE];
-
-       len = snprintf (filename, BUFSIZE, rrd_unix, inst);
-       if ((len > 0) && (len < BUFSIZE))
-               rrd_update_file (host, filename, val, ds_def_unix, ds_num_unix);
-       return;
-} /* static void vserver_unix_write(char *host, char *inst, char *val) */
-
-static void vserver_inet_write (char *host, char *inst, char *val)
-{
-       int  len;
-       char filename[BUFSIZE];
-
-       len = snprintf (filename, BUFSIZE, rrd_inet, inst);
-       if ((len > 0) && (len < BUFSIZE))
-               rrd_update_file (host, filename, val, ds_def_inet, ds_num_inet);
-       return;
-} /* static void vserver_inet_write(char *host, char *inst, char *val) */
-
-static void vserver_inet6_write (char *host, char *inst, char *val)
-{
-       int  len;
-       char filename[BUFSIZE];
-
-       len = snprintf (filename, BUFSIZE, rrd_inet6, inst);
-       if ((len > 0) && (len < BUFSIZE))
-               rrd_update_file (host, filename, val, ds_def_inet6, ds_num_inet6);
-       return;
-} /* static void vserver_inet6_write(char *host, char *inst, char *val) */
 
-static void vserver_other_write (char *host, char *inst, char *val)
-{
-       int  len;
-       char filename[BUFSIZE];
-
-       len = snprintf (filename, BUFSIZE, rrd_other, inst);
-       if ((len > 0) && (len < BUFSIZE))
-               rrd_update_file (host, filename, val, ds_def_other, ds_num_other);
-       return;
-} /* static void vserver_other_write(char *host, char *inst, char *val) */
+       return (0);
+} /* static void vserver_init(void) */
 
-static void vserver_unspec_write (char *host, char *inst, char *val)
+static void traffic_submit (const char *plugin_instance,
+               const char *type_instance, counter_t rx, counter_t tx)
 {
-       int  len;
-       char filename[BUFSIZE];
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       len = snprintf (filename, BUFSIZE, rrd_unspec, inst);
-       if ((len > 0) && (len < BUFSIZE))
-               rrd_update_file (host, filename, val, ds_def_unspec, ds_num_unspec);
-       return;
-} /* static void vserver_unspec_write(char *host, char *inst, char *val) */
+       values[0].counter = rx;
+       values[1].counter = tx;
 
-static void vserver_threads_write (char *host, char *inst, char *val)
-{
-       int  len;
-       char filename[BUFSIZE];
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "vserver");
+       strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+       strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
-       len = snprintf (filename, BUFSIZE, rrd_thread, inst);
-       if ((len > 0) && (len < BUFSIZE))
-               rrd_update_file (host, filename, val, ds_def_threads, ds_num_threads);
-       return;
-} /* static void vserver_threads_write(char *host, char *inst, char *val) */
+       plugin_dispatch_values ("if_octets", &vl);
+} /* void traffic_submit */
 
-static void vserver_load_write (char *host, char *inst, char *val)
+static void load_submit (const char *plugin_instance,
+               gauge_t snum, gauge_t mnum, gauge_t lnum)
 {
-       int  len;
-       char filename[BUFSIZE];
+       value_t values[3];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       len = snprintf (filename, BUFSIZE, rrd_load, inst);
-       if ((len > 0) && (len < BUFSIZE))
-               rrd_update_file (host, filename, val, ds_def_load, ds_num_load);
-       return;
-} /* static void vserver_load_write(char *host, char *inst, char *val) */
-
-static void vserver_procs_write (char *host, char *inst, char *val)
-{
-       int  len;
-       char filename[BUFSIZE];
+       values[0].gauge = snum;
+       values[1].gauge = mnum;
+       values[2].gauge = lnum;
 
-       len = snprintf (filename, BUFSIZE, rrd_procs, inst);
-       if ((len > 0) && (len < BUFSIZE))
-               rrd_update_file (host, filename, val, ds_def_procs, ds_num_procs);
-       return;
-} /* static void vserver_procs_write(char *host, char *inst, char *val) */
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "vserver");
+       strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
 
-static void vserver_memory_write (char *host, char *inst, char *val)
-{
-       int  len;
-       char filename[BUFSIZE];
+       plugin_dispatch_values ("load", &vl);
+}
 
-       len = snprintf (filename, BUFSIZE, rrd_memory, inst);
-       if ((len > 0) && (len < BUFSIZE))
-               rrd_update_file (host, filename, val, ds_def_memory, ds_num_memory);
-       return;
-} /* static void vserver_memory_write(char *host, char *inst, char *val) */
+static void submit_gauge (const char *plugin_instance, const char *type,
+               const char *type_instance, gauge_t value)
 
-#if VSERVER_HAVE_READ
-static void vserver_submit (char *inst, long long unix_in, long long unix_out, 
-               long long unix_failed, long long inet_in, long long inet_out, 
-               long long inet_failed, long long inet6_in, long long inet6_out, 
-               long long inet6_failed, long long other_in, long long other_out,
-               long long other_failed, long long unspec_in, long long unspec_out, 
-               long long unspec_failed, int t_total, int t_running, 
-               int t_uninterruptible, int t_onhold, double avg1, double avg5, 
-               double avg15, int p_total, long long vm, long long vml, long long rss, 
-               long long anon)
 {
-       int  len;
-       char buffer[BUFSIZE];
-
-       len = snprintf (buffer, BUFSIZE, 
-                       "N:%lld:%lld:%lld", unix_in, unix_out, unix_failed);
-
-       if ((len > 0) && (len < BUFSIZE))
-               plugin_submit ("vserver_unix", inst, buffer);
-
-
-       len = snprintf (buffer, BUFSIZE, 
-                       "N:%lld:%lld:%lld", inet_in, inet_out, inet_failed);
-
-       if ((len > 0) && (len < BUFSIZE))
-               plugin_submit ("vserver_inet", inst, buffer);
-
-
-       len = snprintf (buffer, BUFSIZE, 
-                       "N:%lld:%lld:%lld", inet6_in, inet6_out, inet6_failed);
-
-       if ((len > 0) && (len < BUFSIZE))
-               plugin_submit ("vserver_inet6", inst, buffer);
-
-
-       len = snprintf (buffer, BUFSIZE, 
-                       "N:%lld:%lld:%lld", other_in, other_out, other_failed);
-
-       if ((len > 0) && (len < BUFSIZE))
-               plugin_submit ("vserver_other", inst, buffer);
-
-
-       len = snprintf (buffer, BUFSIZE, 
-                       "N:%lld:%lld:%lld", unspec_in, unspec_out, unspec_failed);
-
-       if ((len > 0) && (len < BUFSIZE))
-               plugin_submit ("vserver_unspec", inst, buffer);
-
-
-       len = snprintf (buffer, BUFSIZE, "N:%d:%d:%d:%d",
-                       t_total, t_running, t_uninterruptible, t_onhold);
-
-       if ((len > 0) && (len < BUFSIZE))
-               plugin_submit ("vserver_threads", inst, buffer);
-
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       len = snprintf (buffer, BUFSIZE, "N:%.2f:%.2f:%.2f",
-                       avg1, avg5, avg15);
+       values[0].gauge = value;
 
-       if ((len > 0) && (len < BUFSIZE))
-               plugin_submit ("vserver_load", inst, buffer);
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "vserver");
+       strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+       strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
-
-       len = snprintf (buffer, BUFSIZE, "N:%d",
-                       p_total);
-
-       if ((len > 0) && (len < BUFSIZE))
-               plugin_submit ("vserver_procs", inst, buffer);
-
-
-       len = snprintf (buffer, BUFSIZE, "N:%lld:%lld:%lld:%lld",
-                       vm, vml, rss, anon);
-
-       if ((len > 0) && (len < BUFSIZE))
-               plugin_submit ("vserver_memory", inst, buffer);
-       return;
-} /* static void vserver_submit() */
+       plugin_dispatch_values (type, &vl);
+} /* void submit_gauge */
 
 static inline long long __get_sock_bytes(const char *s)
 {
@@ -338,7 +178,7 @@ static inline long long __get_sock_bytes(const char *s)
        return atoll(s);
 }
 
-static void vserver_read (void)
+static int vserver_read (void)
 {
        DIR                     *proc;
        struct dirent   *dent; /* 42 */
@@ -350,12 +190,13 @@ static void vserver_read (void)
        {
                plugin_complain (LOG_ERR, &complain_obj, "vserver plugin: "
                                "fopen (%s) failed: %s", PROCDIR, strerror (errno));
-               return;
+               return (-1);
        }
        plugin_relief (LOG_NOTICE, &complain_obj, "vserver plugin: "
                        "fopen (%s) succeeded.", PROCDIR);
 
-       while (NULL != (dent = readdir (proc))) {
+       while (NULL != (dent = readdir (proc)))
+       {
                int  len;
                char file[BUFSIZE];
 
@@ -364,24 +205,11 @@ static void vserver_read (void)
 
                char *cols[4];
 
-               long long       unix_s[3]       = {-1, -1, -1};
-               long long       inet[3]         = {-1, -1, -1};
-               long long       inet6[3]        = {-1, -1, -1};
-               long long       other[3]        = {-1, -1, -1};
-               long long       unspec[3]       = {-1, -1, -1};
-               int                     threads[4]      = {-1, -1, -1, -1};
-               double          load[3]         = {-1, -1, -1};
-               /* Just to be consistent ;-) */
-               int                     procs[1]        = {-1};
-               long long       memory[4]       = {-1, -1, -1, -1};
-
                if (dent->d_name[0] == '.')
                        continue;
 
-               /* XXX This check is just the result of a trial-and-error test.
-                * I did not find any documentation describing the d_type field. */
-               if (!(dent->d_type & 0x4))
-                       /* This is not a directory */
+               /* This is not a directory */
+               if (dent->d_type != DT_DIR)
                        continue;
 
                /* socket message accounting */
@@ -389,146 +217,159 @@ static void vserver_read (void)
                if ((len < 0) || (len >= BUFSIZE))
                        continue;
 
-               if (NULL == (fh = fopen (file, "r"))) {
+               if (NULL == (fh = fopen (file, "r")))
                        syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno));
-                       continue;
-               }
 
-               while (NULL != fgets (buffer, BUFSIZE, fh)) {
+               while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh)))
+               {
+                       counter_t rx;
+                       counter_t tx;
+                       char *type_instance;
+
                        if (strsplit (buffer, cols, 4) < 4)
                                continue;
 
-                       if (0 == strcmp (cols[0], "UNIX:")) {
-                               unix_s[0] = __get_sock_bytes (cols[1]);
-                               unix_s[1] = __get_sock_bytes (cols[2]);
-                               unix_s[2] = __get_sock_bytes (cols[3]);
-                       }
-                       else if (0 == strcmp (cols[0], "INET:")) {
-                               inet[0] = __get_sock_bytes (cols[1]);
-                               inet[1] = __get_sock_bytes (cols[2]);
-                               inet[2] = __get_sock_bytes (cols[3]);
-                       }
-                       else if (0 == strcmp (cols[0], "INET6:")) {
-                               inet6[0] = __get_sock_bytes (cols[1]);
-                               inet6[1] = __get_sock_bytes (cols[2]);
-                               inet6[2] = __get_sock_bytes (cols[3]);
-                       }
-                       else if (0 == strcmp (cols[0], "OTHER:")) {
-                               other[0] = __get_sock_bytes (cols[1]);
-                               other[1] = __get_sock_bytes (cols[2]);
-                               other[2] = __get_sock_bytes (cols[3]);
-                       }
-                       else if (0 == strcmp (cols[0], "UNSPEC:")) {
-                               unspec[0] = __get_sock_bytes (cols[1]);
-                               unspec[1] = __get_sock_bytes (cols[2]);
-                               unspec[2] = __get_sock_bytes (cols[3]);
-                       }
-               }
+                       if (0 == strcmp (cols[0], "UNIX:"))
+                               type_instance = "unix";
+                       else if (0 == strcmp (cols[0], "INET:"))
+                               type_instance = "inet";
+                       else if (0 == strcmp (cols[0], "INET6:"))
+                               type_instance = "inet6";
+                       else if (0 == strcmp (cols[0], "OTHER:"))
+                               type_instance = "other";
+                       else if (0 == strcmp (cols[0], "UNSPEC:"))
+                               type_instance = "unspec";
+                       else
+                               continue;
 
-               fclose (fh);
+                       rx = __get_sock_bytes (cols[1]);
+                       tx = __get_sock_bytes (cols[2]);
+                       /* cols[3] == errors */
+
+                       traffic_submit (dent->d_name, type_instance, rx, tx);
+               } /* while (fgets) */
+
+               if (fh != NULL)
+               {
+                       fclose (fh);
+                       fh = NULL;
+               }
 
                /* thread information and load */
                len = snprintf (file, BUFSIZE, PROCDIR "/%s/cvirt", dent->d_name);
                if ((len < 0) || (len >= BUFSIZE))
                        continue;
 
-               if (NULL == (fh = fopen (file, "r"))) {
+               if (NULL == (fh = fopen (file, "r")))
                        syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno));
-                       continue;
-               }
 
-               while (NULL != fgets (buffer, BUFSIZE, fh)) {
+               while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh)))
+               {
                        int n = strsplit (buffer, cols, 4);
 
-                       if (2 == n) {
-                               if (0 == strcmp (cols[0], "nr_threads:")) {
-                                       threads[0] = atoi (cols[1]);
-                               }
-                               else if (0 == strcmp (cols[0], "nr_running:")) {
-                                       threads[1] = atoi (cols[1]);
-                               }
-                               else if (0 == strcmp (cols[0], "nr_unintr:")) {
-                                       threads[2] = atoi (cols[1]);
-                               }
-                               else if (0 == strcmp (cols[0], "nr_onhold:")) {
-                                       threads[3] = atoi (cols[1]);
-                               }
+                       if (2 == n)
+                       {
+                               char   *type_instance;
+                               gauge_t value;
+
+                               if (0 == strcmp (cols[0], "nr_threads:"))
+                                       type_instance = "total";
+                               else if (0 == strcmp (cols[0], "nr_running:"))
+                                       type_instance = "running";
+                               else if (0 == strcmp (cols[0], "nr_unintr:"))
+                                       type_instance = "uninterruptable";
+                               else if (0 == strcmp (cols[0], "nr_onhold:"))
+                                       type_instance = "onhold";
+                               else
+                                       continue;
+
+                               value = atof (cols[1]);
+                               submit_gauge (dent->d_name, "vs_threads", type_instance, value);
                        }
                        else if (4 == n) {
-                               if (0 == strcmp (cols[0], "loadavg:")) {
-                                       load[0] = atof (cols[1]);
-                                       load[1] = atof (cols[2]);
-                                       load[2] = atof (cols[3]);
+                               if (0 == strcmp (cols[0], "loadavg:"))
+                               {
+                                       gauge_t snum = atof (cols[1]);
+                                       gauge_t mnum = atof (cols[2]);
+                                       gauge_t lnum = atof (cols[3]);
+                                       load_submit (dent->d_name, snum, mnum, lnum);
                                }
                        }
-               }
+               } /* while (fgets) */
 
-               fclose (fh);
+               if (fh != NULL)
+               {
+                       fclose (fh);
+                       fh = NULL;
+               }
 
                /* processes and memory usage */
                len = snprintf (file, BUFSIZE, PROCDIR "/%s/limit", dent->d_name);
                if ((len < 0) || (len >= BUFSIZE))
                        continue;
 
-               if (NULL == (fh = fopen (file, "r"))) {
+               if (NULL == (fh = fopen (file, "r")))
                        syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno));
-                       continue;
-               }
 
-               while (NULL != fgets (buffer, BUFSIZE, fh)) {
+               while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh)))
+               {
+                       char *type = "vs_memory";
+                       char *type_instance;
+                       gauge_t value;
+
                        if (strsplit (buffer, cols, 2) < 2)
                                continue;
 
-                       if (0 == strcmp (cols[0], "PROC:")) {
-                               procs[0] = atoi (cols[1]);
-                       }
-                       else if (0 == strcmp (cols[0], "VM:")) {
-                               memory[0] = atoll (cols[1]) * pagesize;
-                       }
-                       else if (0 == strcmp (cols[0], "VML:")) {
-                               memory[1] = atoll (cols[1]) * pagesize;
+                       if (0 == strcmp (cols[0], "PROC:"))
+                       {
+                               type = "vs_processes";
+                               type_instance = "";
+                               value = atof (cols[1]);
                        }
-                       else if (0 == strcmp (cols[0], "RSS:")) {
-                               memory[2] = atoll (cols[1]) * pagesize;
+                       else
+                       {
+                               if (0 == strcmp (cols[0], "VM:"))
+                                       type_instance = "vm";
+                               else if (0 == strcmp (cols[0], "VML:"))
+                                       type_instance = "vml";
+                               else if (0 == strcmp (cols[0], "RSS:"))
+                                       type_instance = "rss";
+                               else if (0 == strcmp (cols[0], "ANON:"))
+                                       type_instance = "anon";
+                               else
+                                       continue;
+
+                               value = atof (cols[1]) * pagesize;
                        }
-                       else if (0 == strcmp (cols[0], "ANON:")) {
-                               memory[3] = atoll (cols[1]) * pagesize;
-                       }
-               }
-
-               fclose (fh);
 
-               /* XXX What to do in case of an error (i.e. some value is
-                * still -1)? */
+                       submit_gauge (dent->d_name, type, type_instance, value);
+               } /* while (fgets) */
 
-               vserver_submit (dent->d_name, unix_s[0], unix_s[1], unix_s[2], 
-                               inet[0], inet[1], inet[2], inet6[0], inet6[1], inet6[2], 
-                               other[0], other[1], other[2], unspec[0], unspec[1], unspec[2],
-                               threads[0], threads[1], threads[2], threads[3], load[0], 
-                               load[1], load[2], procs[0], memory[0], memory[1], memory[2], 
-                               memory[3]);
-       }
+               if (fh != NULL)
+               {
+                       fclose (fh);
+                       fh = NULL;
+               }
+       } /* while (readdir) */
 
        closedir (proc);
-       return;
-} /* static void vserver_read(void) */
-#else
-# define vserver_read NULL
+
+       return (0);
+} /* int vserver_read */
 #endif /* VSERVER_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, vserver_init, vserver_read, NULL);
-       plugin_register ("vserver_unix", NULL, NULL, vserver_unix_write);
-       plugin_register ("vserver_inet", NULL, NULL, vserver_inet_write);
-       plugin_register ("vserver_inet6", NULL, NULL, vserver_inet6_write);
-       plugin_register ("vserver_other", NULL, NULL, vserver_other_write);
-       plugin_register ("vserver_unspec", NULL, NULL, vserver_unspec_write);
-       plugin_register ("vserver_threads", NULL, NULL, vserver_threads_write);
-       plugin_register ("vserver_load", NULL, NULL, vserver_load_write);
-       plugin_register ("vserver_procs", NULL, NULL, vserver_procs_write);
-       plugin_register ("vserver_memory", NULL, NULL, vserver_memory_write);
-       return;
+       plugin_register_data_set (&octets_ds);
+       plugin_register_data_set (&load_ds);
+       plugin_register_data_set (&threads_ds);
+       plugin_register_data_set (&processes_ds);
+       plugin_register_data_set (&memory_ds);
+
+#if VSERVER_HAVE_READ
+       plugin_register_init ("vserver", vserver_init);
+       plugin_register_read ("vserver", vserver_read);
+#endif /* VSERVER_HAVE_READ */
 } /* void module_register(void) */
 
 /* vim: set ts=4 sw=4 noexpandtab : */
index f0b9b01..1041453 100644 (file)
@@ -1,11 +1,10 @@
 /**
  * collectd - src/wireless.c
- * Copyright (C) 2006  Florian octo Forster
+ * Copyright (C) 2006,2007  Florian octo Forster
  *
  * 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.
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -24,9 +23,6 @@
 #include "common.h"
 #include "plugin.h"
 
-#define MODULE_NAME "wireless"
-#define BUFSIZE 1024
-
 #if defined(KERNEL_LINUX)
 # define WIRELESS_HAVE_READ 1
 #else
 
 #define WIRELESS_PROC_FILE "/proc/net/wireless"
 
-static char *filename_template = "wireless-%s.rrd";
-
-static char *ds_def[] =
+static data_source_t data_source_quality[1] =
 {
-       "DS:quality:GAUGE:"COLLECTD_HEARTBEAT":0:U",
-       "DS:power:GAUGE:"COLLECTD_HEARTBEAT":U:0",
-       "DS:noise:GAUGE:"COLLECTD_HEARTBEAT":U:0",
-       NULL
+       {"value", DS_TYPE_GAUGE, 0, NAN}
 };
-static int ds_num = 3;
-
-#if WIRELESS_HAVE_READ
-static int proc_file_found = 0;
-#endif
 
-static void wireless_init (void)
+static data_set_t quality_ds =
 {
-#if WIRELESS_HAVE_READ
-       if (access (WIRELESS_PROC_FILE, R_OK) == 0)
-               proc_file_found = 1;
-       else
-               proc_file_found = 0;
-#endif
-
-       return;
-}
+       "signal_quality", 1, data_source_quality
+};
 
-static void wireless_write (char *host, char *inst, char *val)
+static data_source_t data_source_signal[1] =
 {
-       char file[BUFSIZE];
-       int status;
+       {"value", DS_TYPE_GAUGE, NAN, 0}
+};
 
-       status = snprintf (file, BUFSIZE, filename_template, inst);
-       if (status < 1)
-               return;
-       else if (status >= BUFSIZE)
-               return;
+static data_set_t power_ds =
+{
+       "signal_power", 1, data_source_signal
+};
 
-       rrd_update_file (host, file, val, ds_def, ds_num);
-}
+static data_set_t noise_ds =
+{
+       "signal_noise", 1, data_source_signal
+};
 
 #if WIRELESS_HAVE_READ
 #if 0
@@ -93,27 +73,30 @@ static double wireless_dbm_to_watt (double dbm)
 }
 #endif
 
-static void wireless_submit (char *device,
-               double quality, double power, double noise)
+static void wireless_submit (const char *plugin_instance, const char *type,
+               double value)
 {
-       char buf[BUFSIZE];
-       int  status;
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
-       status = snprintf (buf, BUFSIZE, "%u:%f:%f:%f",
-                       (unsigned int) curtime,
-                       quality, power, noise);
-       if ((status < 1) || (status >= BUFSIZE))
-               return;
+       values[0].gauge = value;
 
-       plugin_submit (MODULE_NAME, device, buf);
-}
+       vl.values = values;
+       vl.values_len = 1;
+       vl.time = time (NULL);
+       strcpy (vl.host, hostname_g);
+       strcpy (vl.plugin, "wireless");
+       strncpy (vl.plugin_instance, plugin_instance,
+                       sizeof (vl.plugin_instance));
 
-static void wireless_read (void)
+       plugin_dispatch_values (type, &vl);
+} /* void wireless_submit */
+
+static int wireless_read (void)
 {
 #ifdef KERNEL_LINUX
-
        FILE *fh;
-       char buffer[BUFSIZE];
+       char buffer[1024];
 
        char   *device;
        double  quality;
@@ -123,19 +106,18 @@ static void wireless_read (void)
        char *fields[8];
        int   numfields;
 
+       int devices_found;
        int len;
 
-       if (!proc_file_found)
-               return;
-
        /* there are a variety of names for the wireless device */
        if ((fh = fopen (WIRELESS_PROC_FILE, "r")) == NULL)
        {
                syslog (LOG_WARNING, "wireless: fopen: %s", strerror (errno));
-               return;
+               return (-1);
        }
 
-       while (fgets (buffer, BUFSIZE, fh) != NULL)
+       devices_found = 0;
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
        {
                numfields = strsplit (buffer, fields, 8);
 
@@ -164,20 +146,32 @@ static void wireless_read (void)
                if (noise == 0.0)
                        noise = 1.0; /* noise <= 0 */
 
-               wireless_submit (device, quality, power, noise);
+               wireless_submit (device, "signal_quality", quality);
+               wireless_submit (device, "signal_power", power);
+               wireless_submit (device, "signal_noise", noise);
+
+               devices_found++;
        }
 
        fclose (fh);
+
+       /* If no wireless devices are present return an error, so the plugin
+        * code delays our read function. */
+       if (devices_found == 0)
+               return (-1);
 #endif /* KERNEL_LINUX */
-}
-#else
-# define wireless_read NULL
+
+       return (0);
+} /* int wireless_read */
 #endif /* WIRELESS_HAVE_READ */
 
 void module_register (void)
 {
-       plugin_register (MODULE_NAME, wireless_init, wireless_read, wireless_write);
-}
+       plugin_register_data_set (&quality_ds);
+       plugin_register_data_set (&power_ds);
+       plugin_register_data_set (&noise_ds);
 
-#undef BUFSIZE
-#undef MODULE_NAME
+#if WIRELESS_HAVE_READ
+       plugin_register_read ("wireless", wireless_read);
+#endif /* WIRELESS_HAVE_READ */
+}