Merge branch 'collectd-4.10' into collectd-5.3
authorFlorian Forster <octo@collectd.org>
Mon, 18 Aug 2014 07:33:29 +0000 (09:33 +0200)
committerFlorian Forster <octo@collectd.org>
Mon, 18 Aug 2014 07:33:29 +0000 (09:33 +0200)
1  2 
configure.in
src/configfile.c
src/curl.c
src/curl_json.c
src/curl_xml.c
src/snmp.c
src/write_http.c

diff --combined configure.in
@@@ -1,5 -1,5 +1,5 @@@
  dnl Process this file with autoconf to produce a configure script.
 -AC_INIT(collectd, m4_esyscmd(./version-gen.sh))
 +AC_INIT(collectd, [m4_esyscmd(./version-gen.sh)])
  AC_CONFIG_SRCDIR(src/collectd.c)
  AC_CONFIG_HEADERS(src/config.h)
  AC_CONFIG_AUX_DIR([libltdl/config])
@@@ -24,7 -24,7 +24,7 @@@ m4_ifdef([LT_PACKAGE_VERSION]
        ]
  )
  
 -AM_INIT_AUTOMAKE(dist-bzip2)
 +AM_INIT_AUTOMAKE([tar-pax dist-bzip2])
  AC_LANG(C)
  
  AC_PREFIX_DEFAULT("/opt/collectd")
@@@ -49,13 -49,6 +49,13 @@@ AC_PROG_YAC
  PKG_PROG_PKG_CONFIG
  
  AC_CHECK_PROG([have_protoc_c], [protoc-c], [yes], [no])
 +AC_CHECK_HEADERS([google/protobuf-c/protobuf-c.h],
 +                 [have_protobuf_c_h="yes"],
 +                 [have_protobuf_c_h="no"])
 +if test "x$have_protoc_c" = "xyes" && test "x$have_protobuf_c_h" != "xyes"
 +then
 +      have_protoc_c="no (unable to find <google/protobuf-c/protobuf-c.h>)"
 +fi
  AM_CONDITIONAL(HAVE_PROTOC_C, test "x$have_protoc_c" = "xyes")
  
  AC_MSG_CHECKING([for kernel type ($host_os)])
@@@ -98,7 -91,6 +98,7 @@@ f
  if test "x$ac_system" = "xSolaris"
  then
        AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Define to enforce POSIX thread semantics under Solaris.])
 +      AC_DEFINE(_REENTRANT,               1, [Define to enable reentrancy interfaces.])
  fi
  if test "x$ac_system" = "xAIX"
  then
@@@ -117,13 -109,9 +117,13 @@@ AC_ARG_ENABLE(standards
  if test "x$enable_standards" = "xyes"
  then
        AC_DEFINE(_ISOC99_SOURCE,        1, [Define to enforce ISO C99 compliance.])
 -      AC_DEFINE(_POSIX_C_SOURCE, 200112L, [Define to enforce POSIX.1-2001 compliance.])
 -      AC_DEFINE(_XOPEN_SOURCE,       600, [Define to enforce X/Open 6 (XSI) compliance.])
 +      AC_DEFINE(_POSIX_C_SOURCE, 200809L, [Define to enforce POSIX.1-2008 compliance.])
 +      AC_DEFINE(_XOPEN_SOURCE,       700, [Define to enforce X/Open 7 (XSI) compliance.])
        AC_DEFINE(_REENTRANT,            1, [Define to enable reentrancy interfaces.])
 +      if test "x$GCC" = "xyes"
 +      then
 +              CFLAGS="$CFLAGS -std=c99"
 +      fi
  fi
  AM_CONDITIONAL(BUILD_FEATURE_STANDARDS, test "x$enable_standards" = "xyes")
  
@@@ -135,7 -123,7 +135,7 @@@ AC_HEADER_SYS_WAI
  AC_HEADER_DIRENT
  AC_HEADER_STDBOOL
  
 -AC_CHECK_HEADERS(stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h)
 +AC_CHECK_HEADERS(stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h fnmatch.h libgen.h)
  
  # For ping library
  AC_CHECK_HEADERS(netinet/in_systm.h, [], [],
@@@ -277,19 -265,7 +277,19 @@@ if test "x$ac_system" = "xDarwin
  then
        AC_CHECK_HEADERS(mach/mach_init.h mach/host_priv.h mach/mach_error.h mach/mach_host.h mach/mach_port.h mach/mach_types.h mach/message.h mach/processor_set.h mach/processor.h mach/processor_info.h mach/task.h mach/thread_act.h mach/vm_region.h mach/vm_map.h mach/vm_prot.h mach/vm_statistics.h mach/kern_return.h)
        AC_CHECK_HEADERS(CoreFoundation/CoreFoundation.h IOKit/IOKitLib.h IOKit/IOTypes.h IOKit/ps/IOPSKeys.h IOKit/IOBSD.h IOKit/storage/IOBlockStorageDriver.h)
 +      # For the battery plugin
 +      AC_CHECK_HEADERS(IOKit/ps/IOPowerSources.h, [], [],
 +[
 +#if HAVE_IOKIT_IOKITLIB_H
 +#  include <IOKit/IOKitLib.h>
 +#endif
 +#if HAVE_IOKIT_IOTYPES_H
 +#  include <IOKit/IOTypes.h>
 +#endif
 +])
 +
  fi
 +
  AC_CHECK_HEADERS(sys/sysctl.h, [], [],
  [
  #if HAVE_SYS_TYPES_H
@@@ -317,22 -293,18 +317,22 @@@ els
  fi
  
  # For hddtemp module
 -AC_CHECK_HEADERS(linux/major.h libgen.h)
 +AC_CHECK_HEADERS(linux/major.h)
  
 -# For the battery plugin
 -AC_CHECK_HEADERS(IOKit/ps/IOPowerSources.h, [], [],
 +# For md module (Linux only)
 +if test "x$ac_system" = "xLinux"
 +then
 +      AC_CHECK_HEADERS(linux/raid/md_u.h,
 +                       [have_linux_raid_md_u_h="yes"],
 +                       [have_linux_raid_md_u_h="no"],
  [
 -#if HAVE_IOKIT_IOKITLIB_H
 -#  include <IOKit/IOKitLib.h>
 -#endif
 -#if HAVE_IOKIT_IOTYPES_H
 -#  include <IOKit/IOTypes.h>
 -#endif
 +#include <sys/ioctl.h>
 +#include <linux/major.h>
 +#include <linux/types.h>
  ])
 +else
 +      have_linux_raid_md_u_h="no"
 +fi
  
  # For the swap module
  have_linux_wireless_h="no"
@@@ -399,18 -371,6 +399,18 @@@ AC_CHECK_HEADERS(linux/if.h, [], []
  #  include <sys/socket.h>
  #endif
  ])
 +AC_CHECK_HEADERS(linux/inet_diag.h, [], [],
 +[
 +#if HAVE_SYS_TYPES_H
 +#  include <sys/types.h>
 +#endif
 +#if HAVE_SYS_SOCKET_H
 +#  include <sys/socket.h>
 +#endif
 +#if HAVE_LINUX_INET_DIAG_H
 +# include <linux/inet_diag.h>
 +#endif
 +])
  AC_CHECK_HEADERS(linux/netdevice.h, [], [],
  [
  #if HAVE_SYS_TYPES_H
  #endif
  ])
  
 +# For ethstat module
 +AC_CHECK_HEADERS(linux/sockios.h,
 +    [have_linux_sockios_h="yes"],
 +    [have_linux_sockios_h="no"],
 +    [
 +#if HAVE_SYS_IOCTL_H
 +# include <sys/ioctl.h>
 +#endif
 +#if HAVE_NET_IF_H
 +# include <net/if.h>
 +#endif
 +    ])
 +AC_CHECK_HEADERS(linux/ethtool.h,
 +    [have_linux_ethtool_h="yes"],
 +    [have_linux_ethtool_h="no"],
 +    [
 +#if HAVE_SYS_IOCTL_H
 +# include <sys/ioctl.h>
 +#endif
 +#if HAVE_NET_IF_H
 +# include <net/if.h>
 +#endif
 +#if HAVE_LINUX_SOCKIOS_H
 +# include <linux/sockios.h>
 +#endif
 +    ])
 +
  # For ipvs module
  have_linux_ip_vs_h="no"
  have_net_ip_vs_h="no"
@@@ -553,24 -486,6 +553,24 @@@ AC_CHECK_HEADERS(netinet/if_ether.h, []
  #endif
  ])
  
 +AC_CHECK_HEADERS(netinet/ip_compat.h)
 +
 +have_net_pfvar_h="no"
 +AC_CHECK_HEADERS(net/pfvar.h,
 +               [have_net_pfvar_h="yes"],
 +               [have_net_pfvar_h="no"],
 +[
 +#if HAVE_SYS_IOCTL_H
 +# include <sys/ioctl.h>
 +#endif
 +#if HAVE_SYS_SOCKET_H
 +# include <sys/socket.h>
 +#endif
 +#if HAVE_NET_IF_H
 +# include <net/if.h>
 +#endif
 +])
 +
  # For the multimeter plugin
  have_termios_h="no"
  AC_CHECK_HEADERS(termios.h, [have_termios_h="yes"])
@@@ -603,12 -518,12 +603,12 @@@ AC_CACHE_CHECK([for strtok_r]
    [c_cv_have_strtok_r_default],
    AC_LINK_IFELSE(
      [AC_LANG_PROGRAM(
 -    [[[
 +[[[
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>
 -    ]]],
 -    [[[
 +]]],
 +[[[
        char buffer[] = "foo,bar,baz";
        char *token;
        char *dummy;
          dummy = NULL;
          printf ("token = %s;\n", token);
        }
 -    ]]])],
 +]]]
 +    )],
      [c_cv_have_strtok_r_default="yes"],
      [c_cv_have_strtok_r_default="no"]
    )
@@@ -636,12 -550,12 +636,12 @@@ the
      [c_cv_have_strtok_r_reentrant],
      AC_LINK_IFELSE(
        [AC_LANG_PROGRAM(
 -      [[[
 +[[[
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>
 -      ]]],
 -      [[[
 +]]],
 +[[[
          char buffer[] = "foo,bar,baz";
          char *token;
          char *dummy;
            dummy = NULL;
            printf ("token = %s;\n", token);
          }
 -      ]]])],
 +]]]
 +      )],
        [c_cv_have_strtok_r_reentrant="yes"],
        [AC_MSG_FAILURE([strtok_r isn't available. Please file a bugreport!])]
      )
@@@ -674,27 -587,6 +674,27 @@@ socket_needs_socket="no
  AC_CHECK_FUNCS(socket, [], AC_CHECK_LIB(socket, socket, [socket_needs_socket="yes"], AC_MSG_ERROR(cannot find socket)))
  AM_CONDITIONAL(BUILD_WITH_LIBSOCKET, test "x$socket_needs_socket" = "xyes")
  
 +clock_gettime_needs_rt="no"
 +clock_gettime_needs_posix4="no"
 +have_clock_gettime="no"
 +AC_CHECK_FUNCS(clock_gettime, [have_clock_gettime="yes"])
 +if test "x$have_clock_gettime" = "xno"
 +then
 +      AC_CHECK_LIB(rt, clock_gettime, [clock_gettime_needs_rt="yes"
 +                                       have_clock_gettime="yes"])
 +fi
 +if test "x$have_clock_gettime" = "xno"
 +then
 +      AC_CHECK_LIB(posix4, clock_gettime, [clock_gettime_needs_posix4="yes"
 +                                           have_clock_gettime="yes"])
 +fi
 +if test "x$have_clock_gettime" = "xyes"
 +then
 +      AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if the clock_gettime(2) function is available.])
 +else
 +      AC_MSG_WARN(cannot find clock_gettime)
 +fi
 +
  nanosleep_needs_rt="no"
  nanosleep_needs_posix4="no"
  AC_CHECK_FUNCS(nanosleep,
          AC_CHECK_LIB(posix4, nanosleep,
              [nanosleep_needs_posix4="yes"],
              AC_MSG_ERROR(cannot find nanosleep))))
 -AM_CONDITIONAL(BUILD_WITH_LIBRT, test "x$nanosleep_needs_rt" = "xyes")
 -AM_CONDITIONAL(BUILD_WITH_LIBPOSIX4, test "x$nanosleep_needs_posix4" = "xyes")
 +
 +AM_CONDITIONAL(BUILD_WITH_LIBRT, test "x$clock_gettime_needs_rt" = "xyes" || test "x$nanosleep_needs_rt" = "xyes")
 +AM_CONDITIONAL(BUILD_WITH_LIBPOSIX4, test "x$clock_gettime_needs_posix4" = "xyes" || test "x$nanosleep_needs_posix4" = "xyes")
  
  AC_CHECK_FUNCS(sysctl, [have_sysctl="yes"], [have_sysctl="no"])
  AC_CHECK_FUNCS(sysctlbyname, [have_sysctlbyname="yes"], [have_sysctlbyname="no"])
@@@ -716,127 -607,13 +716,127 @@@ AC_CHECK_FUNCS(thread_info, [have_threa
  AC_CHECK_FUNCS(statfs, [have_statfs="yes"], [have_statfs="no"])
  AC_CHECK_FUNCS(statvfs, [have_statvfs="yes"], [have_statvfs="no"])
  AC_CHECK_FUNCS(getifaddrs, [have_getifaddrs="yes"], [have_getifaddrs="no"])
 +AC_CHECK_FUNCS(getloadavg, [have_getloadavg="yes"], [have_getloadavg="no"])
  AC_CHECK_FUNCS(syslog, [have_syslog="yes"], [have_syslog="no"])
  AC_CHECK_FUNCS(getutent, [have_getutent="yes"], [have_getutent="no"])
  AC_CHECK_FUNCS(getutxent, [have_getutxent="yes"], [have_getutxent="no"])
 -AC_CHECK_FUNCS(swapctl, [have_swapctl="yes"], [have_swapctl="no"])
  
 -# For load module
 -AC_CHECK_FUNCS(getloadavg, [have_getloadavg="yes"], [have_getloadavg="no"])
 +# Check for strptime {{{
 +if test "x$GCC" = "xyes"
 +then
 +      SAVE_CFLAGS="$CFLAGS"
 +      CFLAGS="$CFLAGS -Wall -Wextra -Werror"
 +fi
 +
 +AC_CHECK_FUNCS(strptime, [have_strptime="yes"], [have_strptime="no"])
 +if test "x$have_strptime" = "xyes"
 +then
 +      AC_CACHE_CHECK([whether strptime is exported by default],
 +                     [c_cv_have_strptime_default],
 +                     AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
 +[[[
 +#include <time.h>
 +]]],
 +[[[
 + struct tm stm;
 + (void) strptime ("2010-12-30%13:42:42", "%Y-%m-%dT%T", &stm);
 +]]]
 +                     )],
 +                     [c_cv_have_strptime_default="yes"],
 +                     [c_cv_have_strptime_default="no"]))
 +fi
 +if test "x$have_strptime" = "xyes" && test "x$c_cv_have_strptime_default" = "xno"
 +then
 +      AC_CACHE_CHECK([whether strptime needs standards mode],
 +                     [c_cv_have_strptime_standards],
 +                     AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
 +[[[
 +#ifndef _ISOC99_SOURCE
 +# define _ISOC99_SOURCE 1
 +#endif
 +#ifndef _POSIX_C_SOURCE
 +# define _POSIX_C_SOURCE 200112L
 +#endif
 +#ifndef _XOPEN_SOURCE
 +# define _XOPEN_SOURCE 500
 +#endif
 +#include <time.h>
 +]]],
 +[[[
 + struct tm stm;
 + (void) strptime ("2010-12-30%13:42:42", "%Y-%m-%dT%T", &stm);
 +]]]
 +                     )],
 +                     [c_cv_have_strptime_standards="yes"],
 +                     [c_cv_have_strptime_standards="no"]))
 +
 +      if test "x$c_cv_have_strptime_standards" = "xyes"
 +      then
 +              AC_DEFINE([STRPTIME_NEEDS_STANDARDS], 1, [Set to true if strptime is only exported in X/Open mode (GNU libc).])
 +      else
 +              have_strptime="no"
 +      fi
 +fi
 +
 +if test "x$GCC" = "xyes"
 +then
 +      CFLAGS="$SAVE_CFLAGS"
 +fi
 +# }}} Check for strptime
 +
 +AC_CHECK_FUNCS(swapctl, [have_swapctl="yes"], [have_swapctl="no"])
 +if test "x$have_swapctl" = "xyes"; then
 +        AC_CACHE_CHECK([whether swapctl takes two arguments],
 +                [c_cv_have_swapctl_two_args],
 +                AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
 +[[[
 +#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64
 +#  undef _FILE_OFFSET_BITS
 +#  undef _LARGEFILE64_SOURCE
 +#endif
 +#include <sys/stat.h>
 +#include <sys/swap.h>
 +]]],
 +[[[
 +int num = swapctl(0, NULL);
 +]]]
 +                        )],
 +                        [c_cv_have_swapctl_two_args="yes"],
 +                        [c_cv_have_swapctl_two_args="no"]
 +                )
 +        )
 +        AC_CACHE_CHECK([whether swapctl takes three arguments],
 +                [c_cv_have_swapctl_three_args],
 +                AC_COMPILE_IFELSE(
 +                        [AC_LANG_PROGRAM(
 +[[[
 +#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64
 +#  undef _FILE_OFFSET_BITS
 +#  undef _LARGEFILE64_SOURCE
 +#endif
 +#include <sys/stat.h>
 +#include <sys/swap.h>
 +]]],
 +[[[
 +int num = swapctl(0, NULL, 0);
 +]]]
 +                        )],
 +                        [c_cv_have_swapctl_three_args="yes"],
 +                        [c_cv_have_swapctl_three_args="no"]
 +                )
 +        )
 +fi
 +# Check for different versions of `swapctl' here..
 +if test "x$have_swapctl" = "xyes"; then
 +        if test "x$c_cv_have_swapctl_two_args" = "xyes"; then
 +                AC_DEFINE(HAVE_SWAPCTL_TWO_ARGS, 1,
 +                          [Define if the function swapctl exists and takes two arguments.])
 +        fi
 +        if test "x$c_cv_have_swapctl_three_args" = "xyes"; then
 +                AC_DEFINE(HAVE_SWAPCTL_THREE_ARGS, 1,
 +                          [Define if the function swapctl exists and takes three arguments.])
 +        fi
 +fi
  
  # Check for NAN
  AC_ARG_WITH(nan-emulation, [AS_HELP_STRING([--with-nan-emulation], [use emulated NAN. For crosscompiling only.])],
  if test "x$nan_type" = "xnone"; then
    AC_CACHE_CHECK([whether NAN is defined by default],
      [c_cv_have_nan_default],
 -    AC_COMPILE_IFELSE(
 -      [AC_LANG_PROGRAM(
 -      [[[
 +    AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
 +[[[
  #include <stdlib.h>
  #include <math.h>
  static double foo = NAN;
 -      ]]],
 -      [[[
 +]]],
 +[[[
         if (isnan (foo))
          return 0;
         else
        return 1;
 -      ]]])],
 +]]]
 +      )],
        [c_cv_have_nan_default="yes"],
        [c_cv_have_nan_default="no"]
      )
  if test "x$nan_type" = "xnone"; then
    AC_CACHE_CHECK([whether NAN is defined by __USE_ISOC99],
      [c_cv_have_nan_isoc],
 -    AC_COMPILE_IFELSE(
 -      [AC_LANG_PROGRAM(
 -      [[[
 +    AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
 +[[[
  #include <stdlib.h>
  #define __USE_ISOC99 1
  #include <math.h>
  static double foo = NAN;
 -      ]]],
 -      [[[
 +]]],
 +[[[
         if (isnan (foo))
          return 0;
         else
        return 1;
 -      ]]])],
 +]]]
 +      )],
        [c_cv_have_nan_isoc="yes"],
        [c_cv_have_nan_isoc="no"]
      )
@@@ -906,8 -683,9 +906,8 @@@ if test "x$nan_type" = "xnone"; the
    LDFLAGS="$LDFLAGS -lm"
    AC_CACHE_CHECK([whether NAN can be defined by 0/0],
      [c_cv_have_nan_zero],
 -    AC_RUN_IFELSE(
 -      [AC_LANG_PROGRAM(
 -      [[[
 +    AC_RUN_IFELSE([AC_LANG_PROGRAM(
 +[[[
  #include <stdlib.h>
  #include <math.h>
  #ifdef NAN
  # define isnan(f) ((f) != (f))
  #endif
  static double foo = NAN;
 -      ]]],
 -      [[[
 +]]],
 +[[[
         if (isnan (foo))
          return 0;
         else
        return 1;
 -      ]]])],
 +]]]
 +      )],
        [c_cv_have_nan_zero="yes"],
        [c_cv_have_nan_zero="no"]
      )
@@@ -967,8 -744,9 +967,8 @@@ fi; fi; f
  if test "x$fp_layout_type" = "xunknown"; then
    AC_CACHE_CHECK([if doubles are stored in x86 representation],
      [c_cv_fp_layout_need_nothing],
 -    AC_RUN_IFELSE(
 -      [AC_LANG_PROGRAM(
 -      [[[
 +    AC_RUN_IFELSE([AC_LANG_PROGRAM(
 +[[[
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>
  #if HAVE_STDBOOL_H
  # include <stdbool.h>
  #endif
 -      ]]],
 -      [[[
 +]]],
 +[[[
        uint64_t i0;
        uint64_t i1;
        uint8_t c[8];
                return (0);
        else
                return (1);
 -      ]]])],
 +]]]
 +      )],
        [c_cv_fp_layout_need_nothing="yes"],
        [c_cv_fp_layout_need_nothing="no"]
      )
  if test "x$fp_layout_type" = "xunknown"; then
    AC_CACHE_CHECK([if endianflip converts to x86 representation],
      [c_cv_fp_layout_need_endianflip],
 -    AC_RUN_IFELSE(
 -      [AC_LANG_PROGRAM(
 -      [[[
 +    AC_RUN_IFELSE([AC_LANG_PROGRAM(
 +[[[
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>
                         (((uint64_t)(A) & 0x0000000000ff0000LL) << 24) | \
                         (((uint64_t)(A) & 0x000000000000ff00LL) << 40) | \
                         (((uint64_t)(A) & 0x00000000000000ffLL) << 56))
 -      ]]],
 -      [[[
 +]]],
 +[[[
        uint64_t i0;
        uint64_t i1;
        uint8_t c[8];
                return (0);
        else
                return (1);
 -      ]]])],
 +]]]
 +      )],
        [c_cv_fp_layout_need_endianflip="yes"],
        [c_cv_fp_layout_need_endianflip="no"]
      )
  if test "x$fp_layout_type" = "xunknown"; then
    AC_CACHE_CHECK([if intswap converts to x86 representation],
      [c_cv_fp_layout_need_intswap],
 -    AC_RUN_IFELSE(
 -      [AC_LANG_PROGRAM(
 -      [[[
 +    AC_RUN_IFELSE([AC_LANG_PROGRAM(
 +[[[
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>
  #endif
  #define intswap(A)    ((((uint64_t)(A) & 0xffffffff00000000LL) >> 32) | \
                         (((uint64_t)(A) & 0x00000000ffffffffLL) << 32))
 -      ]]],
 -      [[[
 +]]],
 +[[[
        uint64_t i0;
        uint64_t i1;
        uint8_t c[8];
                return (0);
        else
                return (1);
 -      ]]])],
 +]]]
 +      )],
        [c_cv_fp_layout_need_intswap="yes"],
        [c_cv_fp_layout_need_intswap="no"]
      )
@@@ -1152,16 -929,14 +1152,16 @@@ if test "x$have_getmntent" = "xc"; the
        AC_CACHE_CHECK([whether getmntent takes one argument],
                [c_cv_have_one_getmntent],
                AC_COMPILE_IFELSE(
 -                      [AC_LANG_PROGRAM([[AC_INCLUDES_DEFAULT
 -#include "$srcdir/src/utils_mount.h"]],
 -                              [[[
 -                               FILE *fh;
 -                               struct mntent *me;
 -                               fh = setmntent ("/etc/mtab", "r");
 -                               me = getmntent (fh);
 -                              ]]]
 +                      [AC_LANG_PROGRAM(
 +[[[
 +#include "$srcdir/src/utils_mount.h"
 +]]],
 +[[[
 +FILE *fh;
 +struct mntent *me;
 +fh = setmntent ("/etc/mtab", "r");
 +me = getmntent (fh);
 +]]]
                        )],
                        [c_cv_have_one_getmntent="yes"],
                        [c_cv_have_one_getmntent="no"]
        AC_CACHE_CHECK([whether getmntent takes two arguments],
                [c_cv_have_two_getmntent],
                AC_COMPILE_IFELSE(
 -                      [AC_LANG_PROGRAM([[AC_INCLUDES_DEFAULT
 -#include "$srcdir/src/utils_mount.h"]],
 -                              [[[
 +                      [AC_LANG_PROGRAM(
 +[[[
 +#include "$srcdir/src/utils_mount.h"
 +]]],
 +[[[
                                 FILE *fh;
                                 struct mnttab mt;
                                 int status;
                                 fh = fopen ("/etc/mnttab", "r");
                                 status = getmntent (fh, &mt);
 -                              ]]]
 +]]]
                        )],
                        [c_cv_have_two_getmntent="yes"],
                        [c_cv_have_two_getmntent="no"]
  AC_MSG_CHECKING([if have htonll defined])
  
      have_htonll="no"
 -    AC_LINK_IFELSE([
 -       AC_LANG_PROGRAM([[[
 +    AC_LINK_IFELSE([AC_LANG_PROGRAM(
 +[[[
  #include <sys/types.h>
  #include <netinet/in.h>
  #if HAVE_INTTYPES_H
  # include <inttypes.h>
  #endif
 -       ]]], [[[
 +]]],
 +[[[
            return htonll(0);
 -       ]]])
 -    ], [
 +]]]
 +    )],
 +    [
        have_htonll="yes"
        AC_DEFINE(HAVE_HTONLL, 1, [Define if the function htonll exists.])
      ])
@@@ -1254,13 -1025,6 +1254,13 @@@ AC_CHECK_MEMBERS([struct net_device_sta
        #include <linux/if.h>
        #include <linux/netdevice.h>
        ])
 +AC_CHECK_MEMBERS([struct inet_diag_req.id, struct inet_diag_req.idiag_states],
 +      [AC_DEFINE(HAVE_STRUCT_LINUX_INET_DIAG_REQ, 1, [Define if struct inet_diag_req exists and is usable.])],
 +      [],
 +      [
 +      #include <linux/inet_diag.h>
 +      ])
 +
  
  AC_CHECK_MEMBERS([struct ip_mreqn.imr_ifindex], [],
        [],
@@@ -1279,6 -1043,7 +1279,6 @@@ AC_CHECK_MEMBERS([struct kinfo_proc.ki_
                have_struct_kinfo_proc_freebsd="no"
        ],
        [
 -AC_INCLUDES_DEFAULT
  #include <kvm.h>
  #include <sys/param.h>
  #include <sys/sysctl.h>
@@@ -1295,6 -1060,7 +1295,6 @@@ AC_CHECK_MEMBERS([struct kinfo_proc.kp_
                have_struct_kinfo_proc_openbsd="no"
        ],
        [
 -AC_INCLUDES_DEFAULT
  #include <sys/param.h>
  #include <sys/sysctl.h>
  #include <kvm.h>
@@@ -1355,7 -1121,6 +1355,7 @@@ AC_CHECK_MEMBERS([kstat_io_t.nwritten, 
  #
  # Checks for libraries begin here
  #
 +
  with_libresolv="yes"
  AC_CHECK_LIB(resolv, res_search,
  [
@@@ -1371,8 -1136,8 +1371,8 @@@ AC_CHECK_LIB(hal,libhal_device_property
             [with_libhal="no"])
  if test "x$with_libhal" = "xyes"; then
        if test "x$PKG_CONFIG" != "x"; then
-               BUILD_WITH_LIBHAL_CFLAGS="`pkg-config --cflags hal`"
-               BUILD_WITH_LIBHAL_LIBS="`pkg-config --libs hal`"
+               BUILD_WITH_LIBHAL_CFLAGS="`$PKG_CONFIG --cflags hal`"
+               BUILD_WITH_LIBHAL_LIBS="`$PKG_CONFIG --libs hal`"
                AC_SUBST(BUILD_WITH_LIBHAL_CFLAGS)
                AC_SUBST(BUILD_WITH_LIBHAL_LIBS)
        fi
  if test "x$with_perfstat" = "xyes"
  then
         AC_DEFINE(HAVE_PERFSTAT, 1, [Define to 1 if you have the 'perfstat' library (-lperfstat)])
 +       # struct members pertaining to donation have been added to libperfstat somewhere between AIX5.3ML5 and AIX5.3ML9
 +       AC_CHECK_MEMBER([perfstat_partition_type_t.b.donate_enabled], [], [], [[#include <libperfstat.h]])
 +       if test "x$av_cv_member_perfstat_partition_type_t_b_donate_enabled" = "xyes"
 +       then
 +              AC_DEFINE(PERFSTAT_SUPPORTS_DONATION, 1, [Define to 1 if your version of the 'perfstat' library supports donation])
 +       fi
  fi
  AM_CONDITIONAL(BUILD_WITH_PERFSTAT, test "x$with_perfstat" = "xyes")
  
@@@ -1446,12 -1205,13 +1446,12 @@@ AM_CONDITIONAL(BUILD_WITH_LIBKSTAT, tes
  AM_CONDITIONAL(BUILD_WITH_LIBDEVINFO, test "x$with_devinfo" = "xyes")
  
  with_libiokit="no"
 -AC_CHECK_LIB(IOKit, IOServiceGetMatchingServices,
 -[
 +if test "x$ac_system" = "xDarwin"
 +then
        with_libiokit="yes"
 -], 
 -[
 +else
        with_libiokit="no"
 -])
 +fi
  AM_CONDITIONAL(BUILD_WITH_LIBIOKIT, test "x$with_libiokit" = "xyes")
  
  with_libkvm="no"
  fi
  AM_CONDITIONAL(BUILD_WITH_LIBKVM_OPENFILES, test "x$with_kvm_openfiles" = "xyes")
  
 +# --with-libcredis {{{
 +AC_ARG_WITH(libcredis, [AS_HELP_STRING([--with-libcredis@<:@=PREFIX@:>@], [Path to libcredis.])],
 +[
 + if test "x$withval" = "xyes"
 + then
 +       with_libcredis="yes"
 + else if test "x$withval" = "xno"
 + then
 +       with_libcredis="no"
 + else
 +       with_libcredis="yes"
 +       LIBCREDIS_CPPFLAGS="$LIBCREDIS_CPPFLAGS -I$withval/include"
 +       LIBCREDIS_LDFLAGS="$LIBCREDIS_LDFLAGS -L$withval/lib"
 + fi; fi
 +],
 +[with_libcredis="yes"])
 +
 +SAVE_CPPFLAGS="$CPPFLAGS"
 +SAVE_LDFLAGS="$LDFLAGS"
 +
 +CPPFLAGS="$CPPFLAGS $LIBCREDIS_CPPFLAGS"
 +LDFLAGS="$LDFLAGS $LIBCREDIS_LDFLAGS"
 +
 +if test "x$with_libcredis" = "xyes"
 +then
 +      if test "x$LIBCREDIS_CPPFLAGS" != "x"
 +      then
 +              AC_MSG_NOTICE([libcredis CPPFLAGS: $LIBCREDIS_CPPFLAGS])
 +      fi
 +      AC_CHECK_HEADERS(credis.h,
 +      [with_libcredis="yes"],
 +      [with_libcredis="no (credis.h not found)"])
 +fi
 +if test "x$with_libcredis" = "xyes"
 +then
 +      if test "x$LIBCREDIS_LDFLAGS" != "x"
 +      then
 +              AC_MSG_NOTICE([libcredis LDFLAGS: $LIBCREDIS_LDFLAGS])
 +      fi
 +      AC_CHECK_LIB(credis, credis_info,
 +      [with_libcredis="yes"],
 +      [with_libcredis="no (symbol 'credis_info' not found)"])
 +
 +fi
 +
 +CPPFLAGS="$SAVE_CPPFLAGS"
 +LDFLAGS="$SAVE_LDFLAGS"
 +
 +if test "x$with_libcredis" = "xyes"
 +then
 +      BUILD_WITH_LIBCREDIS_CPPFLAGS="$LIBCREDIS_CPPFLAGS"
 +      BUILD_WITH_LIBCREDIS_LDFLAGS="$LIBCREDIS_LDFLAGS"
 +      AC_SUBST(BUILD_WITH_LIBCREDIS_CPPFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBCREDIS_LDFLAGS)
 +fi
 +AM_CONDITIONAL(BUILD_WITH_LIBCREDIS, test "x$with_libcredis" = "xyes")
 +# }}}
 +
  # --with-libcurl {{{
  with_curl_config="curl-config"
  with_curl_cflags=""
@@@ -1862,8 -1564,6 +1862,8 @@@ the
  
        if test "$with_libgcrypt" != "no"; then
                AM_PATH_LIBGCRYPT(1:1.2.0,,with_libgcrypt="no (version 1.2.0+ required)")
 +              GCRYPT_CPPFLAGS="$LIBGCRYPT_CPPFLAGS $LIBGCRYPT_CFLAGS"
 +              GCRYPT_LIBS="$LIBGCRYPT_LIBS"
        fi
  fi
  
@@@ -2027,7 -1727,7 +2027,7 @@@ the
        if test -d "$with_java_home"
        then
                AC_MSG_CHECKING([for jni.h])
 -              TMPVAR=`find "$with_java_home" -name jni.h -type f -exec 'dirname' '{}' ';' | head -n 1`
 +              TMPVAR=`find "$with_java_home" -name jni.h -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1`
                if test "x$TMPVAR" != "x"
                then
                        AC_MSG_RESULT([found in $TMPVAR])
                fi
  
                AC_MSG_CHECKING([for jni_md.h])
 -              TMPVAR=`find "$with_java_home" -name jni_md.h -type f -exec 'dirname' '{}' ';' | head -n 1`
 +              TMPVAR=`find "$with_java_home" -name jni_md.h -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1`
                if test "x$TMPVAR" != "x"
                then
                        AC_MSG_RESULT([found in $TMPVAR])
                fi
  
                AC_MSG_CHECKING([for libjvm.so])
 -              TMPVAR=`find "$with_java_home" -name libjvm.so -type f -exec 'dirname' '{}' ';' | head -n 1`
 +              TMPVAR=`find "$with_java_home" -name libjvm.so -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1`
                if test "x$TMPVAR" != "x"
                then
                        AC_MSG_RESULT([found in $TMPVAR])
                if test "x$JAVAC" = "x"
                then
                        AC_MSG_CHECKING([for javac])
 -                      TMPVAR=`find "$with_java_home" -name javac -type f | head -n 1`
 +                      TMPVAR=`find "$with_java_home" -name javac -type f 2>/dev/null | head -n 1`
                        if test "x$TMPVAR" != "x"
                        then
                                JAVAC="$TMPVAR"
                if test "x$JAR" = "x"
                then
                        AC_MSG_CHECKING([for jar])
 -                      TMPVAR=`find "$with_java_home" -name jar -type f | head -n 1`
 +                      TMPVAR=`find "$with_java_home" -name jar -type f 2>/dev/null | head -n 1`
                        if test "x$TMPVAR" != "x"
                        then
                                JAR="$TMPVAR"
  fi
  if test "x$with_libmodbus" = "xuse_pkgconfig"
  then
 -      AC_MSG_NOTICE([Checking for modbus using $PKG_CONFIG])
 -      $PKG_CONFIG --exists 'modbus' 2>/dev/null
 +      AC_MSG_NOTICE([Checking for libmodbus using $PKG_CONFIG])
 +      $PKG_CONFIG --exists 'libmodbus' 2>/dev/null
        if test $? -ne 0
        then
 -              with_libmodbus="no (pkg-config doesn't know library)"
 +              with_libmodbus="no (pkg-config doesn't know libmodbus)"
        fi
  fi
  if test "x$with_libmodbus" = "xuse_pkgconfig"
  then
 -      with_libmodbus_cflags="`$PKG_CONFIG --cflags 'modbus'`"
 +      with_libmodbus_cflags="`$PKG_CONFIG --cflags 'libmodbus'`"
        if test $? -ne 0
        then
                with_libmodbus="no ($PKG_CONFIG failed)"
        fi
 -      with_libmodbus_libs="`$PKG_CONFIG --libs 'modbus'`"
 +      with_libmodbus_libs="`$PKG_CONFIG --libs 'libmodbus'`"
        if test $? -ne 0
        then
                with_libmodbus="no ($PKG_CONFIG failed)"
@@@ -2297,9 -1997,9 +2297,9 @@@ the
        CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags"
        LDFLAGS="$LDFLAGS $with_libmodbus_libs"
  
 -      AC_CHECK_LIB(modbus, modbus_init_tcp,
 +      AC_CHECK_LIB(modbus, modbus_connect,
                     [with_libmodbus="yes"],
 -                   [with_libmodbus="no (symbol modbus_init_tcp not found)"])
 +                   [with_libmodbus="no (symbol modbus_connect not found)"])
  
        CPPFLAGS="$SAVE_CPPFLAGS"
        LDFLAGS="$SAVE_LDFLAGS"
  fi
  # }}}
  
 +# --with-libmongoc {{{
 +AC_ARG_WITH(libmongoc, [AS_HELP_STRING([--with-libmongoc@<:@=PREFIX@:>@], [Path to libmongoc.])],
 +[
 + if test "x$withval" = "xyes"
 + then
 +       with_libmongoc="yes"
 + else if test "x$withval" = "xno"
 + then
 +       with_libmongoc="no"
 + else
 +       with_libmongoc="yes"
 +       LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS -I$withval/include"
 +       LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS -L$withval/lib"
 + fi; fi
 +],
 +[with_libmongoc="yes"])
 +
 +SAVE_CPPFLAGS="$CPPFLAGS"
 +SAVE_LDFLAGS="$LDFLAGS"
 +
 +CPPFLAGS="$CPPFLAGS $LIBMONGOC_CPPFLAGS"
 +LDFLAGS="$LDFLAGS $LIBMONGOC_LDFLAGS"
 +
 +if test "x$with_libmongoc" = "xyes"
 +then
 +      if test "x$LIBMONGOC_CPPFLAGS" != "x"
 +      then
 +              AC_MSG_NOTICE([libmongoc CPPFLAGS: $LIBMONGOC_CPPFLAGS])
 +      fi
 +      AC_CHECK_HEADERS(mongo.h,
 +      [with_libmongoc="yes"],
 +      [with_libmongoc="no ('mongo.h' not found)"],
 +[#if HAVE_STDINT_H
 +# define MONGO_HAVE_STDINT 1
 +#else
 +# define MONGO_USE_LONG_LONG_INT 1
 +#endif
 +])
 +fi
 +if test "x$with_libmongoc" = "xyes"
 +then
 +      if test "x$LIBMONGOC_LDFLAGS" != "x"
 +      then
 +              AC_MSG_NOTICE([libmongoc LDFLAGS: $LIBMONGOC_LDFLAGS])
 +      fi
 +      AC_CHECK_LIB(mongoc, mongo_run_command,
 +      [with_libmongoc="yes"],
 +      [with_libmongoc="no (symbol 'mongo_run_command' not found)"])
 +fi
 +
 +CPPFLAGS="$SAVE_CPPFLAGS"
 +LDFLAGS="$SAVE_LDFLAGS"
 +
 +if test "x$with_libmongoc" = "xyes"
 +then
 +      BUILD_WITH_LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS"
 +      BUILD_WITH_LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS"
 +      AC_SUBST(BUILD_WITH_LIBMONGOC_CPPFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBMONGOC_LDFLAGS)
 +fi
 +AM_CONDITIONAL(BUILD_WITH_LIBMONGOC, test "x$with_libmongoc" = "xyes")
 +# }}}
 +
  # --with-libmysql {{{
  with_mysql_config="mysql_config"
  with_mysql_cflags=""
  #include <sys/socket.h>])
  
          AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
 -                           [[[
 -                            #include <stdio.h>
 -                            #include <sys/types.h>
 -                            #include <asm/types.h>
 -                            #include <sys/socket.h>
 -                            #include <linux/netlink.h>
 -                            #include <linux/rtnetlink.h>
 -                            ]]], [[[
 -                                int retval = TCA_STATS2;
 -                                return (retval);
 -                                ]]]
 -                            )],
 -                            [AC_DEFINE([HAVE_TCA_STATS2], [1], [True if the enum-member TCA_STATS2 exists])])
 +[[[
 +#include <stdio.h>
 +#include <sys/types.h>
 +#include <asm/types.h>
 +#include <sys/socket.h>
 +#include <linux/netlink.h>
 +#include <linux/rtnetlink.h>
 +]]],
 +[[[
 +int retval = TCA_STATS2;
 +return (retval);
 +]]]
 +      )],
 +      [AC_DEFINE([HAVE_TCA_STATS2], [1], [True if the enum-member TCA_STATS2 exists])])
  
        AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
 -[[[#include <stdio.h>
 +[[[
 +#include <stdio.h>
  #include <sys/types.h>
  #include <asm/types.h>
  #include <sys/socket.h>
  #include <linux/netlink.h>
  #include <linux/rtnetlink.h>
 -]]], [[[
 -int main (void)
 -{
 -      int retval = TCA_STATS;
 -      return (retval);
 -}]]])],
 -      [AC_DEFINE([HAVE_TCA_STATS], 1, [True if the enum-member TCA_STATS exists])]
 -      []);
 +]]],
 +[[[
 +int retval = TCA_STATS;
 +return (retval);
 +]]]
 +      )],
 +      [AC_DEFINE([HAVE_TCA_STATS], 1, [True if the enum-member TCA_STATS exists])])
  
        CFLAGS="$SAVE_CFLAGS"
  fi
        AC_CACHE_CHECK(
                [if function 'rtnl_dump_filter' expects five arguments],
                [c_cv_rtnl_dump_filter_five_args],
 -              AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
 -AC_INCLUDES_DEFAULT
 +              AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
 +[[[
 +#include <stdio.h>
 +#include <sys/types.h>
  #include <asm/types.h>
  #include <sys/socket.h>
  #if HAVE_LIBNETLINK_H
  #elif HAVE_LINUX_LIBNETLINK_H
  # include <linux/libnetlink.h>
  #endif
 -                              ]], [[[
 +]]],
 +[[[
  if (rtnl_dump_filter(NULL, NULL, NULL, NULL, NULL))
        return 1;
  return 0;
 -                              ]]]
 -                      )],
 -                      [c_cv_rtnl_dump_filter_five_args="yes"],
 -                      [c_cv_rtnl_dump_filter_five_args="no"]
 -              )
 +]]]
 +      )],
 +      [c_cv_rtnl_dump_filter_five_args="yes"],
 +      [c_cv_rtnl_dump_filter_five_args="no"]
        )
 +)
  
        AC_CACHE_CHECK(
                [if function 'rtnl_dump_filter' expects three arguments],
                [c_cv_rtnl_dump_filter_three_args],
                AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
 -                              [[
 -AC_INCLUDES_DEFAULT
 +[[[
 +#include <stdio.h>
 +#include <sys/types.h>
  #include <asm/types.h>
  #include <sys/socket.h>
  #if HAVE_LIBNETLINK_H
  #elif HAVE_LINUX_LIBNETLINK_H
  # include <linux/libnetlink.h>
  #endif
 -                              ]], [[[
 +]]],
 +[[[
  if (rtnl_dump_filter(NULL, NULL, NULL))
        return 1;
  return 0;
 -                              ]]]
 -                      )],
 -                      [c_cv_rtnl_dump_filter_three_args="yes"],
 -                      [c_cv_rtnl_dump_filter_three_args="no"]
 -              )
 +]]]
 +      )],
 +      [c_cv_rtnl_dump_filter_three_args="yes"],
 +      [c_cv_rtnl_dump_filter_three_args="no"]
        )
 +)
  
        CFLAGS="$SAVE_CFLAGS"
  
@@@ -2857,7 -2488,7 +2857,7 @@@ the
        fi
        AC_CHECK_HEADERS(oping.h,
        [with_liboping="yes"],
 -      [with_liboping="no ('oping.h' not found)"])
 +      [with_liboping="no (oping.h not found)"])
  fi
  if test "x$with_liboping" = "xyes"
  then
  if test "x$with_oracle" = "xyes"
  then
        SAVE_CPPFLAGS="$CPPFLAGS"
 -      SAVE_LDFLAGS="$LDFLAGS"
 +      SAVE_LIBS="$LIBS"
        CPPFLAGS="$CPPFLAGS $with_oracle_cppflags"
 -      LDFLAGS="$LDFLAGS $with_oracle_libs"
 +      LIBS="$LIBS $with_oracle_libs"
  
        AC_CHECK_FUNC(OCIEnvCreate, [with_oracle="yes"], [with_oracle="no (Symbol 'OCIEnvCreate' not found)"])
  
        CPPFLAGS="$SAVE_CPPFLAGS"
 -      LDFLAGS="$SAVE_LDFLAGS"
 +      LIBS="$SAVE_LIBS"
  fi
  if test "x$with_oracle" = "xyes"
  then
  fi
  if test "x$with_libpcap" = "xyes"
  then
 -      AC_CHECK_HEADERS(pcap-bpf.h)
 +      AC_CHECK_HEADERS(pcap-bpf.h,,
 +                       [with_libpcap="no (pcap-bpf.h not found)"])
 +fi
 +if test "x$with_libpcap" = "xyes"
 +then
 +      AC_CACHE_CHECK([whether libpcap has PCAP_ERROR_IFACE_NOT_UP],
 +                     [c_cv_libpcap_have_pcap_error_iface_not_up],
 +                     AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
 +[[[
 +#include <pcap.h>
 +]]],
 +[[[
 +  int val = PCAP_ERROR_IFACE_NOT_UP;
 +]]]
 +                     )],
 +                     [c_cv_libpcap_have_pcap_error_iface_not_up="yes"],
 +                     [c_cv_libpcap_have_pcap_error_iface_not_up="no"]))
 +fi
 +if test "x$c_cv_libpcap_have_pcap_error_iface_not_up" != "xyes"
 +then
 +              with_libpcap="no (pcap.h misses PCAP_ERROR_IFACE_NOT_UP)"
  fi
  AM_CONDITIONAL(BUILD_WITH_LIBPCAP, test "x$with_libpcap" = "xyes")
  # }}}
@@@ -3100,20 -2711,20 +3100,20 @@@ dnl ARCHFLAGS="" -> disable multi -arc
  
    AC_CACHE_CHECK([for libperl],
      [c_cv_have_libperl],
 -    AC_LINK_IFELSE(
 -      [AC_LANG_PROGRAM(
 -      [[[
 +    AC_LINK_IFELSE([AC_LANG_PROGRAM(
 +[[[
  #define PERL_NO_GET_CONTEXT
  #include <EXTERN.h>
  #include <perl.h>
  #include <XSUB.h>
 -      ]]],
 -      [[[
 +]]],
 +[[[
         dTHX;
         load_module (PERL_LOADMOD_NOIMPORT,
                         newSVpv ("Collectd::Plugin::FooBar", 24),
                         Nullsv);
 -      ]]])],
 +]]]
 +      )],
        [c_cv_have_libperl="yes"],
        [c_cv_have_libperl="no"]
      )
@@@ -3145,8 -2756,9 +3145,8 @@@ the
  
        AC_CACHE_CHECK([if perl supports ithreads],
                [c_cv_have_perl_ithreads],
 -              AC_LINK_IFELSE(
 -                      [AC_LANG_PROGRAM(
 -                      [[[
 +              AC_LINK_IFELSE([AC_LANG_PROGRAM(
 +[[[
  #include <EXTERN.h>
  #include <perl.h>
  #include <XSUB.h>
  #if !defined(USE_ITHREADS)
  # error "Perl does not support ithreads!"
  #endif /* !defined(USE_ITHREADS) */
 -                      ]]],
 -                      [[[ ]]])],
 +]]],
 +[[[ ]]]
 +                      )],
                        [c_cv_have_perl_ithreads="yes"],
                        [c_cv_have_perl_ithreads="no"]
                )
  
        AC_CACHE_CHECK([for broken Perl_load_module()],
                [c_cv_have_broken_perl_load_module],
 -              AC_LINK_IFELSE(
 -                      [AC_LANG_PROGRAM(
 -                      [[[
 +              AC_LINK_IFELSE([AC_LANG_PROGRAM(
 +[[[
  #define PERL_NO_GET_CONTEXT
  #include <EXTERN.h>
  #include <perl.h>
  #include <XSUB.h>
 -                      ]]],
 -                      [[[
 +]]],
 +[[[
                         dTHX;
                         load_module (PERL_LOADMOD_NOIMPORT,
                             newSVpv ("Collectd::Plugin::FooBar", 24),
                             Nullsv);
 -                      ]]])],
 +]]]
 +                      )],
                        [c_cv_have_broken_perl_load_module="no"],
                        [c_cv_have_broken_perl_load_module="yes"]
                )
  fi
  # }}} --with-python
  
 +# --with-librabbitmq {{{
 +with_librabbitmq_cppflags=""
 +with_librabbitmq_ldflags=""
 +AC_ARG_WITH(librabbitmq, [AS_HELP_STRING([--with-librabbitmq@<:@=PREFIX@:>@], [Path to librabbitmq.])],
 +[
 +      if test "x$withval" != "xno" && test "x$withval" != "xyes"
 +      then
 +              with_librabbitmq_cppflags="-I$withval/include"
 +              with_librabbitmq_ldflags="-L$withval/lib"
 +              with_librabbitmq="yes"
 +      else
 +              with_librabbitmq="$withval"
 +      fi
 +],
 +[
 +      with_librabbitmq="yes"
 +])
 +SAVE_CPPFLAGS="$CPPFLAGS"
 +SAVE_LDFLAGS="$LDFLAGS"
 +CPPFLAGS="$CPPFLAGS $with_librabbitmq_cppflags"
 +LDFLAGS="$LDFLAGS $with_librabbitmq_ldflags"
 +if test "x$with_librabbitmq" = "xyes"
 +then
 +      AC_CHECK_HEADERS(amqp.h, [with_librabbitmq="yes"], [with_librabbitmq="no (amqp.h not found)"])
 +fi
 +if test "x$with_librabbitmq" = "xyes"
 +then
 +      # librabbitmq up to version 0.9.1 provides "library_errno", later
 +      # versions use "library_error". The library does not provide a version
 +      # macro :( Use "AC_CHECK_MEMBERS" (plural) for automatic defines.
 +      AC_CHECK_MEMBERS([amqp_rpc_reply_t.library_errno],,,
 +                       [
 +#if HAVE_STDLIB_H
 +# include <stdlib.h>
 +#endif
 +#if HAVE_STDIO_H
 +# include <stdio.h>
 +#endif
 +#if HAVE_STDINT_H
 +# include <stdint.h>
 +#endif
 +#if HAVE_INTTYPES_H
 +# include <inttypes.h>
 +#endif
 +#include <amqp.h>
 +                         ])
 +fi
 +if test "x$with_librabbitmq" = "xyes"
 +then
 +      AC_CHECK_LIB(rabbitmq, amqp_basic_publish, [with_librabbitmq="yes"], [with_librabbitmq="no (Symbol 'amqp_basic_publish' not found)"])
 +fi
 +if test "x$with_librabbitmq" = "xyes"
 +then
 +      BUILD_WITH_LIBRABBITMQ_CPPFLAGS="$with_librabbitmq_cppflags"
 +      BUILD_WITH_LIBRABBITMQ_LDFLAGS="$with_librabbitmq_ldflags"
 +      BUILD_WITH_LIBRABBITMQ_LIBS="-lrabbitmq"
 +      AC_SUBST(BUILD_WITH_LIBRABBITMQ_CPPFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBRABBITMQ_LDFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBRABBITMQ_LIBS)
 +      AC_DEFINE(HAVE_LIBRABBITMQ, 1, [Define if librabbitmq is present and usable.])
 +fi
 +CPPFLAGS="$SAVE_CPPFLAGS"
 +LDFLAGS="$SAVE_LDFLAGS"
 +AM_CONDITIONAL(BUILD_WITH_LIBRABBITMQ, test "x$with_librabbitmq" = "xyes")
 +
 +with_amqp_tcp_socket="no"
 +if test "x$with_librabbitmq" = "xyes"
 +then
 +      SAVE_CPPFLAGS="$CPPFLAGS"
 +      SAVE_LDFLAGS="$LDFLAGS"
 +      SAVE_LIBS="$LIBS"
 +      CPPFLAGS="$CPPFLAGS $with_librabbitmq_cppflags"
 +      LDFLAGS="$LDFLAGS $with_librabbitmq_ldflags"
 +      LIBS="-lrabbitmq"
 +
 +      AC_CHECK_HEADERS(amqp_tcp_socket.h amqp_socket.h)
 +      AC_CHECK_FUNC(amqp_tcp_socket_new, [with_amqp_tcp_socket="yes"], [with_amqp_tcp_socket="no"])
 +      if test "x$with_amqp_tcp_socket" = "xyes"
 +      then
 +              AC_DEFINE(HAVE_AMQP_TCP_SOCKET, 1,
 +                              [Define if librabbitmq provides the new TCP socket interface.])
 +      fi
 +
 +      AC_CHECK_DECLS(amqp_socket_close,
 +                              [amqp_socket_close_decl="yes"], [amqp_socket_close_decl="no"],
 +                              [[
 +#include <amqp.h>
 +#ifdef HAVE_AMQP_TCP_SOCKET_H
 +# include <amqp_tcp_socket.h>
 +#endif
 +#ifdef HAVE_AMQP_SOCKET_H
 +# include <amqp_socket.h>
 +#endif
 +                              ]])
 +
 +      CPPFLAGS="$SAVE_CPPFLAGS"
 +      LDFLAGS="$SAVE_LDFLAGS"
 +      LIBS="$SAVE_LIBS"
 +fi
 +# }}}
 +
  # --with-librouteros {{{
  AC_ARG_WITH(librouteros, [AS_HELP_STRING([--with-librouteros@<:@=PREFIX@:>@], [Path to librouteros.])],
  [
@@@ -3615,7 -3125,7 +3615,7 @@@ the
        fi
        AC_CHECK_HEADERS(routeros_api.h,
        [with_librouteros="yes"],
 -      [with_librouteros="no ('routeros_api.h' not found)"])
 +      [with_librouteros="no (routeros_api.h not found)"])
  fi
  if test "x$with_librouteros" = "xyes"
  then
@@@ -3814,7 -3324,7 +3814,7 @@@ the
      if test "$?" != "0"
      then
        with_libstatgrab_pkg_config="no"
 -      with_libstatgrab="no ($PKG_CONFIG doesn't know libstatgrab)"
 +      with_libstatgrab="no (pkg-config doesn't know libstatgrab)"
        temp_result="not found"
      fi
      AC_MSG_RESULT([$temp_result])
@@@ -3924,8 -3434,8 +3924,8 @@@ the
    if $PKG_CONFIG --exists tokyotyrant
    then
      with_libtokyotyrant_cppflags="$with_libtokyotyrant_cppflags `$PKG_CONFIG --cflags tokyotyrant`"
-     with_libtokyotyrant_ldflags="$with_libtokyotyrant_ldflags `pkg-config --libs-only-L tokyotyrant`"
-     with_libtokyotyrant_libs="$with_libtokyotyrant_libs `pkg-config --libs-only-l tokyotyrant`"
+     with_libtokyotyrant_ldflags="$with_libtokyotyrant_ldflags `$PKG_CONFIG --libs-only-L tokyotyrant`"
+     with_libtokyotyrant_libs="$with_libtokyotyrant_libs `$PKG_CONFIG --libs-only-l tokyotyrant`"
    fi
  fi
  
@@@ -4034,7 -3544,7 +4034,7 @@@ the
        $PKG_CONFIG --exists 'libupsclient' 2>/dev/null
        if test $? -ne 0
        then
 -              with_libupsclient="no (pkg-config doesn't know library)"
 +              with_libupsclient="no (pkg-config doesn't know libupsclient)"
        fi
  fi
  if test "x$with_libupsclient" = "xuse_pkgconfig"
  AM_CONDITIONAL(BUILD_WITH_LIBYAJL, test "x$with_libyajl" = "xyes")
  # }}}
  
 +# --with-libvarnish {{{
 +with_libvarnish_cppflags=""
 +with_libvarnish_cflags=""
 +with_libvarnish_libs=""
 +AC_ARG_WITH(libvarnish, [AS_HELP_STRING([--with-libvarnish@<:@=PREFIX@:>@], [Path to libvarnish.])],
 +[
 +      if test "x$withval" = "xno"
 +      then
 +              with_libvarnish="no"
 +      else if test "x$withval" = "xyes"
 +      then
 +              with_libvarnish="use_pkgconfig"
 +      else if test -d "$with_libvarnish/lib"
 +      then
 +              AC_MSG_NOTICE([Not checking for libvarnish: Manually configured])
 +              with_libvarnish_cflags="-I$withval/include"
 +              with_libvarnish_libs="-L$withval/lib -lvarnishapi"
 +              with_libvarnish="yes"
 +      fi; fi; fi
 +],
 +[with_libvarnish="use_pkgconfig"])
 +
 +# configure using pkg-config
 +if test "x$with_libvarnish" = "xuse_pkgconfig"
 +then
 +      if test "x$PKG_CONFIG" = "x"
 +      then
 +              with_libvarnish="no (Don't have pkg-config)"
 +      fi
 +fi
 +if test "x$with_libvarnish" = "xuse_pkgconfig"
 +then
 +      AC_MSG_NOTICE([Checking for varnishapi using $PKG_CONFIG])
 +      $PKG_CONFIG --exists 'varnishapi' 2>/dev/null
 +      if test $? -ne 0
 +      then
 +              with_libvarnish="no (pkg-config doesn't know varnishapi)"
 +      fi
 +fi
 +if test "x$with_libvarnish" = "xuse_pkgconfig"
 +then
 +      with_libvarnish_cflags="`$PKG_CONFIG --cflags 'varnishapi'`"
 +      if test $? -ne 0
 +      then
 +              with_libvarnish="no ($PKG_CONFIG failed)"
 +      fi
 +      with_libvarnish_libs="`$PKG_CONFIG --libs 'varnishapi'`"
 +      if test $? -ne 0
 +      then
 +              with_libvarnish="no ($PKG_CONFIG failed)"
 +      fi
 +fi
 +if test "x$with_libvarnish" = "xuse_pkgconfig"
 +then
 +      with_libvarnish="yes"
 +fi
 +
 +# with_libvarnish_cflags and with_libvarnish_libs are set up now, let's do
 +# the actual checks.
 +if test "x$with_libvarnish" = "xyes"
 +then
 +      SAVE_CPPFLAGS="$CPPFLAGS"
 +      CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags"
 +      AC_CHECK_HEADERS(varnish/varnishapi.h, [], [with_libvarnish="no (varnish/varnishapi.h not found)"])
 +
 +      CPPFLAGS="$SAVE_CPPFLAGS"
 +fi
 +if test "x$with_libvarnish" = "xyes"
 +then
 +      SAVE_CPPFLAGS="$CPPFLAGS"
 +      #SAVE_LDFLAGS="$LDFLAGS"
 +
 +      CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags"
 +      #LDFLAGS="$LDFLAGS $with_libvarnish_libs"
 +
 +    AC_CHECK_HEADERS(varnish/vsc.h,
 +        [AC_DEFINE([HAVE_VARNISH_V3], [1], [Varnish 3 API support])],
 +        [AC_DEFINE([HAVE_VARNISH_V2], [1], [Varnish 2 API support])])
 +
 +      CPPFLAGS="$SAVE_CPPFLAGS"
 +      #LDFLAGS="$SAVE_LDFLAGS"
 +fi
 +if test "x$with_libvarnish" = "xyes"
 +then
 +      BUILD_WITH_LIBVARNISH_CFLAGS="$with_libvarnish_cflags"
 +      BUILD_WITH_LIBVARNISH_LIBS="$with_libvarnish_libs"
 +      AC_SUBST(BUILD_WITH_LIBVARNISH_CFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBVARNISH_LIBS)
 +fi
 +# }}}
 +
  # pkg-config --exists 'libxml-2.0'; pkg-config --exists libvirt {{{
  with_libxml2="no (pkg-config isn't available)"
  with_libxml2_cflags=""
@@@ -4324,30 -3743,30 +4324,30 @@@ with_libvirt_cflags="
  with_libvirt_ldflags=""
  if test "x$PKG_CONFIG" != "x"
  then
-       pkg-config --exists 'libxml-2.0' 2>/dev/null
+       $PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null
        if test "$?" = "0"
        then
                with_libxml2="yes"
        else
 -              with_libxml2="no (pkg-config doesn't know library)"
 +              with_libxml2="no (pkg-config doesn't know libxml-2.0)"
        fi
  
-       pkg-config --exists libvirt 2>/dev/null
+       $PKG_CONFIG --exists libvirt 2>/dev/null
        if test "$?" = "0"
        then
                with_libvirt="yes"
        else
 -              with_libvirt="no (pkg-config doesn't know library)"
 +              with_libvirt="no (pkg-config doesn't know libvirt)"
        fi
  fi
  if test "x$with_libxml2" = "xyes"
  then
-       with_libxml2_cflags="`pkg-config --cflags libxml-2.0`"
+       with_libxml2_cflags="`$PKG_CONFIG --cflags libxml-2.0`"
        if test $? -ne 0
        then
                with_libxml2="no"
        fi
-       with_libxml2_ldflags="`pkg-config --libs libxml-2.0`"
+       with_libxml2_ldflags="`$PKG_CONFIG --libs libxml-2.0`"
        if test $? -ne 0
        then
                with_libxml2="no"
@@@ -4387,12 -3806,12 +4387,12 @@@ if test "x$with_libxml2" = "xyes"; the
  fi
  if test "x$with_libvirt" = "xyes"
  then
-       with_libvirt_cflags="`pkg-config --cflags libvirt`"
+       with_libvirt_cflags="`$PKG_CONFIG --cflags libvirt`"
        if test $? -ne 0
        then
                with_libvirt="no"
        fi
-       with_libvirt_ldflags="`pkg-config --libs libvirt`"
+       with_libvirt_ldflags="`$PKG_CONFIG --libs libvirt`"
        if test $? -ne 0
        then
                with_libvirt="no"
@@@ -4454,7 -3873,7 +4454,7 @@@ the
        $PKG_CONFIG --exists OpenIPMIpthread 2>/dev/null
        if test "$?" != "0"
        then
 -              with_libopenipmipthread="no ($PKG_CONFIG doesn't know OpenIPMIpthread)"
 +              with_libopenipmipthread="no (pkg-config doesn't know OpenIPMIpthread)"
        fi
        AC_MSG_RESULT([$with_libopenipmipthread])
  fi
  
  PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
                [with_libnotify="yes"],
 -              [with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"])
 +              [if test "x$LIBNOTIFY_PKG_ERRORS" = "x"; then
 +                       with_libnotify="no"
 +               else
 +                       with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"
 +               fi])
  
  # Check for enabled/disabled features
  #
@@@ -4659,8 -4074,6 +4659,8 @@@ plugin_curl_xml="no
  plugin_df="no"
  plugin_disk="no"
  plugin_entropy="no"
 +plugin_ethstat="no"
 +plugin_fscache="no"
  plugin_interface="no"
  plugin_ipmi="no"
  plugin_ipvs="no"
@@@ -4670,7 -4083,7 +4670,7 @@@ plugin_load="no
  plugin_memory="no"
  plugin_multimeter="no"
  plugin_nfs="no"
 -plugin_fscache="no"
 +plugin_numa="no"
  plugin_perl="no"
  plugin_processes="no"
  plugin_protocols="no"
        plugin_cpufreq="yes"
        plugin_disk="yes"
        plugin_entropy="yes"
 +      plugin_fscache="yes"
        plugin_interface="yes"
        plugin_irq="yes"
        plugin_load="yes"
        plugin_memory="yes"
        plugin_nfs="yes"
 -      plugin_fscache="yes"
 +      plugin_numa="yes"
        plugin_processes="yes"
        plugin_protocols="yes"
        plugin_serial="yes"
  fi
  
  # AIX
 +
 +if test "x$ac_system" = "xAIX"
 +then
 +        plugin_tcpconns="yes"
 +fi
 +
  if test "x$with_perfstat" = "xyes"
  then
        plugin_cpu="yes"
 +      plugin_contextswitch="yes"
        plugin_disk="yes"
        plugin_memory="yes"
        plugin_swap="yes"
        plugin_interface="yes"
        plugin_load="yes"
 +      plugin_uptime="yes"
  fi
  
  if test "x$with_procinfo" = "xyes"
  # Solaris
  if test "x$with_kstat" = "xyes"
  then
 +      plugin_nfs="yes"
        plugin_uptime="yes"
        plugin_zfs_arc="yes"
  fi
@@@ -4774,6 -4177,11 +4774,6 @@@ the
        plugin_tape="yes"
  fi
  
 -if test "x$have_sys_swap_h$with_kstat$ac_system" = "xyesyesSolaris"
 -then
 -      plugin_swap="yes"
 -fi
 -
  # libstatgrab
  if test "x$with_libstatgrab" = "xyes"
  then
  if test "x$with_libcurl" = "xyes" && test "x$with_libxml2" = "xyes"
  then
        plugin_ascent="yes"
 -      plugin_bind="yes"
 +      if test "x$have_strptime" = "xyes"
 +      then
 +              plugin_bind="yes"
 +      fi
  fi
  
  if test "x$with_libopenipmipthread" = "xyes"
@@@ -4818,15 -4223,11 +4818,15 @@@ if test "x$have_sysctl" = "xyes
  then
        plugin_cpu="yes"
        plugin_memory="yes"
 -      plugin_swap="yes"
        plugin_uptime="yes"
 +      if test "x$ac_system" = "xDarwin"
 +      then
 +              plugin_swap="yes"
 +      fi
  fi
  if test "x$have_sysctlbyname" = "xyes"
  then
 +      plugin_contextswitch="yes"
        plugin_cpu="yes"
        plugin_memory="yes"
        plugin_tcpconns="yes"
        fi
  fi
  
 +if test "x$have_linux_sockios_h$have_linux_ethtool_h" = "xyesyes"
 +then
 +      plugin_ethstat="yes"
 +fi
 +
  if test "x$have_getifaddrs" = "xyes"
  then
        plugin_interface="yes"
@@@ -4919,7 -4315,7 +4919,7 @@@ the
        plugin_swap="yes"
  fi
  
 -if test "x$have_swapctl" = "xyes"
 +if test "x$have_swapctl" = "xyes" && test "x$c_cv_have_swapctl_two_args" = "xyes"
  then
        plugin_swap="yes"
  fi
@@@ -4959,8 -4355,6 +4959,8 @@@ AC_ARG_ENABLE([all-plugins]
  
  m4_divert_once([HELP_ENABLE], [])
  
 +AC_PLUGIN([aggregation], [yes],                [Aggregation plugin])
 +AC_PLUGIN([amqp],        [$with_librabbitmq],  [AMQP output plugin])
  AC_PLUGIN([apache],      [$with_libcurl],      [Apache httpd statistics])
  AC_PLUGIN([apcups],      [yes],                [Statistics of UPSes by APC])
  AC_PLUGIN([apple_sensors], [$with_libiokit],   [Apple's hardware sensors])
@@@ -4981,7 -4375,6 +4981,7 @@@ AC_PLUGIN([disk],        [$plugin_disk]
  AC_PLUGIN([dns],         [$with_libpcap],      [DNS traffic analysis])
  AC_PLUGIN([email],       [yes],                [EMail statistics])
  AC_PLUGIN([entropy],     [$plugin_entropy],    [Entropy statistics])
 +AC_PLUGIN([ethstat],     [$plugin_ethstat],    [Stats from NIC driver])
  AC_PLUGIN([exec],        [yes],                [Execution of external programs])
  AC_PLUGIN([filecount],   [yes],                [Count files in directories])
  AC_PLUGIN([fscache],     [$plugin_fscache],    [fscache statistics])
@@@ -4996,7 -4389,6 +4996,7 @@@ AC_PLUGIN([java],        [$with_java]
  AC_PLUGIN([libvirt],     [$plugin_libvirt],    [Virtual machine statistics])
  AC_PLUGIN([load],        [$plugin_load],       [System load])
  AC_PLUGIN([logfile],     [yes],                [File logging plugin])
 +AC_PLUGIN([lpar],        [$with_perfstat],     [AIX logical partitions statistics])
  AC_PLUGIN([madwifi],     [$have_linux_wireless_h], [Madwifi wireless statistics])
  AC_PLUGIN([match_empty_counter], [yes],        [The empty counter match])
  AC_PLUGIN([match_hashed], [yes],               [The hashed match])
@@@ -5004,7 -4396,6 +5004,7 @@@ AC_PLUGIN([match_regex], [yes]
  AC_PLUGIN([match_timediff], [yes],             [The timediff match])
  AC_PLUGIN([match_value], [yes],                [The value match])
  AC_PLUGIN([mbmon],       [yes],                [Query mbmond])
 +AC_PLUGIN([md],          [$have_linux_raid_md_u_h], [md (Linux software RAID) devices])
  AC_PLUGIN([memcachec],   [$with_libmemcached], [memcachec statistics])
  AC_PLUGIN([memcached],   [yes],                [memcached statistics])
  AC_PLUGIN([memory],      [$plugin_memory],     [Memory usage])
@@@ -5019,14 -4410,12 +5019,14 @@@ AC_PLUGIN([nginx],       [$with_libcurl
  AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications])
  AC_PLUGIN([notify_email], [$with_libesmtp],    [Email notifier])
  AC_PLUGIN([ntpd],        [yes],                [NTPd statistics])
 +AC_PLUGIN([numa],        [$plugin_numa],       [NUMA virtual memory statistics])
  AC_PLUGIN([nut],         [$with_libupsclient], [Network UPS tools statistics])
  AC_PLUGIN([olsrd],       [yes],                [olsrd statistics])
  AC_PLUGIN([onewire],     [$with_libowcapi],    [OneWire sensor statistics])
  AC_PLUGIN([openvpn],     [yes],                [OpenVPN client statistics])
  AC_PLUGIN([oracle],      [$with_oracle],       [Oracle plugin])
  AC_PLUGIN([perl],        [$plugin_perl],       [Embed a Perl interpreter])
 +AC_PLUGIN([pf],          [$have_net_pfvar_h],  [BSD packet filter (PF) statistics])
  # FIXME: Check for libevent, too.
  AC_PLUGIN([pinba],       [$have_protoc_c],     [Pinba statistics])
  AC_PLUGIN([ping],        [$with_liboping],     [Network latency statistics])
@@@ -5035,7 -4424,6 +5035,7 @@@ AC_PLUGIN([powerdns],    [yes]
  AC_PLUGIN([processes],   [$plugin_processes],  [Process statistics])
  AC_PLUGIN([protocols],   [$plugin_protocols],  [Protocol (IP, TCP, ...) statistics])
  AC_PLUGIN([python],      [$with_python],       [Embed a Python interpreter])
 +AC_PLUGIN([redis],       [$with_libcredis],    [Redis plugin])
  AC_PLUGIN([routeros],    [$with_librouteros],  [RouterOS plugin])
  AC_PLUGIN([rrdcached],   [$librrd_rrdc_update], [RRDTool output plugin])
  AC_PLUGIN([rrdtool],     [$with_librrd],       [RRDTool output plugin])
@@@ -5046,32 -4434,24 +5046,32 @@@ AC_PLUGIN([swap],        [$plugin_swap]
  AC_PLUGIN([syslog],      [$have_syslog],       [Syslog logging plugin])
  AC_PLUGIN([table],       [yes],                [Parsing of tabular data])
  AC_PLUGIN([tail],        [yes],                [Parsing of logfiles])
 +AC_PLUGIN([tail_csv],    [yes],                [Parsing of CSV files])
  AC_PLUGIN([tape],        [$plugin_tape],       [Tape drive statistics])
  AC_PLUGIN([target_notification], [yes],        [The notification target])
  AC_PLUGIN([target_replace], [yes],             [The replace target])
  AC_PLUGIN([target_scale],[yes],                [The scale target])
  AC_PLUGIN([target_set],  [yes],                [The set target])
 +AC_PLUGIN([target_v5upgrade], [yes],           [The v5upgrade target])
  AC_PLUGIN([tcpconns],    [$plugin_tcpconns],   [TCP connection statistics])
  AC_PLUGIN([teamspeak2],  [yes],                [TeamSpeak2 server statistics])
  AC_PLUGIN([ted],         [$plugin_ted],        [Read The Energy Detective values])
  AC_PLUGIN([thermal],     [$plugin_thermal],    [Linux ACPI thermal zone statistics])
 +AC_PLUGIN([threshold],   [yes],                [Threshold checking plugin])
  AC_PLUGIN([tokyotyrant], [$with_libtokyotyrant],  [TokyoTyrant database statistics])
  AC_PLUGIN([unixsock],    [yes],                [Unixsock communication plugin])
  AC_PLUGIN([uptime],      [$plugin_uptime],     [Uptime statistics])
  AC_PLUGIN([users],       [$plugin_users],      [User statistics])
  AC_PLUGIN([uuid],        [yes],                [UUID as hostname plugin])
 +AC_PLUGIN([varnish],     [$with_libvarnish],   [Varnish cache statistics])
  AC_PLUGIN([vmem],        [$plugin_vmem],       [Virtual memory statistics])
  AC_PLUGIN([vserver],     [$plugin_vserver],    [Linux VServer statistics])
  AC_PLUGIN([wireless],    [$plugin_wireless],   [Wireless statistics])
 +AC_PLUGIN([write_graphite], [yes],             [Graphite / Carbon output plugin])
  AC_PLUGIN([write_http],  [$with_libcurl],      [HTTP output plugin])
 +AC_PLUGIN([write_mongodb], [$with_libmongoc],  [MongoDB output plugin])
 +AC_PLUGIN([write_redis], [$with_libcredis],    [Redis output plugin])
 +AC_PLUGIN([write_riemann], [$have_protoc_c],   [Riemann output plugin])
  AC_PLUGIN([xmms],        [$with_libxmms],      [XMMS statistics])
  AC_PLUGIN([zfs_arc],     [$plugin_zfs_arc],    [ZFS ARC statistics])
  
@@@ -5168,7 -4548,6 +5168,7 @@@ the
  fi
  
  dnl Perl bindings
 +PERL_BINDINGS_OPTIONS="PREFIX=${prefix}"
  AC_ARG_WITH(perl-bindings, [AS_HELP_STRING([--with-perl-bindings@<:@=OPTIONS@:>@], [Options passed to "perl Makefile.PL".])],
  [
        if test "x$withval" != "xno" && test "x$withval" != "xyes"
                PERL_BINDINGS_OPTIONS="$withval"
                with_perl_bindings="yes"
        else
 -              PERL_BINDINGS_OPTIONS=""
                with_perl_bindings="$withval"
        fi
  ],
  [
 -      PERL_BINDINGS_OPTIONS=""
        if test -n "$perl_interpreter"
        then
                with_perl_bindings="yes"
@@@ -5211,9 -4592,9 +5211,9 @@@ AC_SUBST(LCC_VERSION_PATCH
  AC_SUBST(LCC_VERSION_EXTRA)
  AC_SUBST(LCC_VERSION_STRING)
  
 -AC_CONFIG_FILES(src/libcollectdclient/lcc_features.h)
 +AC_CONFIG_FILES(src/libcollectdclient/collectd/lcc_features.h)
  
 -AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/owniptc/Makefile src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile)
 +AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile)
  
  if test "x$with_librrd" = "xyes" \
        && test "x$librrd_threadsafe" != "xyes"
@@@ -5245,7 -4626,6 +5245,7 @@@ Configuration
    Libraries:
      libcurl . . . . . . . $with_libcurl
      libdbi  . . . . . . . $with_libdbi
 +    libcredis . . . . . . $with_libcredis
      libesmtp  . . . . . . $with_libesmtp
      libganglia  . . . . . $with_libganglia
      libgcrypt . . . . . . $with_libgcrypt
      libperl . . . . . . . $with_libperl
      libpq . . . . . . . . $with_libpq
      libpthread  . . . . . $with_libpthread
 +    librabbitmq . . . . . $with_librabbitmq
      librouteros . . . . . $with_librouteros
      librrd  . . . . . . . $with_librrd
      libsensors  . . . . . $with_libsensors
      libstatgrab . . . . . $with_libstatgrab
      libtokyotyrant  . . . $with_libtokyotyrant
      libupsclient  . . . . $with_libupsclient
 +    libvarnish  . . . . . $with_libvarnish
      libvirt . . . . . . . $with_libvirt
      libxml2 . . . . . . . $with_libxml2
      libxmms . . . . . . . $with_libxmms
      perl  . . . . . . . . $with_perl_bindings
  
    Modules:
 +    aggregation . . . . . $enable_aggregation
 +    amqp    . . . . . . . $enable_amqp
      apache  . . . . . . . $enable_apache
      apcups  . . . . . . . $enable_apcups
      apple_sensors . . . . $enable_apple_sensors
      dns . . . . . . . . . $enable_dns
      email . . . . . . . . $enable_email
      entropy . . . . . . . $enable_entropy
 +    ethstat . . . . . . . $enable_ethstat
      exec  . . . . . . . . $enable_exec
      filecount . . . . . . $enable_filecount
      fscache . . . . . . . $enable_fscache
      libvirt . . . . . . . $enable_libvirt
      load  . . . . . . . . $enable_load
      logfile . . . . . . . $enable_logfile
 +    lpar  . . . . . . . . $enable_lpar
      madwifi . . . . . . . $enable_madwifi
      match_empty_counter . $enable_match_empty_counter
      match_hashed  . . . . $enable_match_hashed
      match_timediff  . . . $enable_match_timediff
      match_value . . . . . $enable_match_value
      mbmon . . . . . . . . $enable_mbmon
 +    md  . . . . . . . . . $enable_md
      memcachec . . . . . . $enable_memcachec
      memcached . . . . . . $enable_memcached
      memory  . . . . . . . $enable_memory
      notify_desktop  . . . $enable_notify_desktop
      notify_email  . . . . $enable_notify_email
      ntpd  . . . . . . . . $enable_ntpd
 +    numa  . . . . . . . . $enable_numa
      nut . . . . . . . . . $enable_nut
      olsrd . . . . . . . . $enable_olsrd
      onewire . . . . . . . $enable_onewire
      openvpn . . . . . . . $enable_openvpn
      oracle  . . . . . . . $enable_oracle
      perl  . . . . . . . . $enable_perl
 +    pf  . . . . . . . . . $enable_pf
      pinba . . . . . . . . $enable_pinba
      ping  . . . . . . . . $enable_ping
      postgresql  . . . . . $enable_postgresql
      processes . . . . . . $enable_processes
      protocols . . . . . . $enable_protocols
      python  . . . . . . . $enable_python
 +    redis . . . . . . . . $enable_redis
      routeros  . . . . . . $enable_routeros
      rrdcached . . . . . . $enable_rrdcached
      rrdtool . . . . . . . $enable_rrdtool
      syslog  . . . . . . . $enable_syslog
      table . . . . . . . . $enable_table
      tail  . . . . . . . . $enable_tail
 +    tail_csv  . . . . . . $enable_tail_csv
      tape  . . . . . . . . $enable_tape
      target_notification . $enable_target_notification
      target_replace  . . . $enable_target_replace
      target_scale  . . . . $enable_target_scale
      target_set  . . . . . $enable_target_set
 +    target_v5upgrade  . . $enable_target_v5upgrade
      tcpconns  . . . . . . $enable_tcpconns
      teamspeak2  . . . . . $enable_teamspeak2
      ted . . . . . . . . . $enable_ted
      thermal . . . . . . . $enable_thermal
 +    threshold . . . . . . $enable_threshold
      tokyotyrant . . . . . $enable_tokyotyrant
      unixsock  . . . . . . $enable_unixsock
      uptime  . . . . . . . $enable_uptime
      users . . . . . . . . $enable_users
      uuid  . . . . . . . . $enable_uuid
 +    varnish . . . . . . . $enable_varnish
      vmem  . . . . . . . . $enable_vmem
      vserver . . . . . . . $enable_vserver
      wireless  . . . . . . $enable_wireless
 +    write_graphite  . . . $enable_write_graphite
      write_http  . . . . . $enable_write_http
 +    write_mongodb . . . . $enable_write_mongodb
 +    write_redis . . . . . $enable_write_redis
 +    write_riemann . . . . $enable_write_riemann
      xmms  . . . . . . . . $enable_xmms
      zfs_arc . . . . . . . $enable_zfs_arc
  
diff --combined src/configfile.c
@@@ -1,6 -1,6 +1,6 @@@
  /**
   * collectd - src/configfile.c
 - * Copyright (C) 2005-2009  Florian octo Forster
 + * Copyright (C) 2005-2011  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
@@@ -17,7 -17,7 +17,7 @@@
   * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
   *
   * Authors:
 - *   Florian octo Forster <octo at verplant.org>
 + *   Florian octo Forster <octo at collectd.org>
   *   Sebastian tokkee Harl <sh at tokkee.org>
   **/
  
  #include "plugin.h"
  #include "configfile.h"
  #include "types_list.h"
 -#include "utils_threshold.h"
  #include "filter_chain.h"
  
  #if HAVE_WORDEXP_H
  # include <wordexp.h>
  #endif /* HAVE_WORDEXP_H */
  
 +#if HAVE_FNMATCH_H
 +# include <fnmatch.h>
 +#endif /* HAVE_FNMATCH_H */
 +
 +#if HAVE_LIBGEN_H
 +# include <libgen.h>
 +#endif /* HAVE_LIBGEN_H */
 +
  #define ESCAPE_NULL(str) ((str) == NULL ? "(null)" : (str))
  
  /*
@@@ -54,7 -47,6 +54,7 @@@ typedef struct cf_callbac
        int  (*callback) (const char *, const char *);
        const char **keys;
        int    keys_num;
 +      plugin_ctx_t ctx;
        struct cf_callback *next;
  } cf_callback_t;
  
@@@ -62,7 -54,6 +62,7 @@@ typedef struct cf_complex_callback_
  {
        char *type;
        int (*callback) (oconfig_item_t *);
 +      plugin_ctx_t ctx;
        struct cf_complex_callback_s *next;
  } cf_complex_callback_t;
  
@@@ -98,22 -89,21 +98,22 @@@ static cf_value_map_t cf_value_map[] 
        {"PluginDir",  dispatch_value_plugindir},
        {"LoadPlugin", dispatch_loadplugin}
  };
 -static int cf_value_map_num = STATIC_ARRAY_LEN (cf_value_map);
 +static int cf_value_map_num = STATIC_ARRAY_SIZE (cf_value_map);
  
  static cf_global_option_t cf_global_options[] =
  {
        {"BaseDir",     NULL, PKGLOCALSTATEDIR},
        {"PIDFile",     NULL, PIDFILE},
        {"Hostname",    NULL, NULL},
 -      {"FQDNLookup",  NULL, "false"},
 -      {"Interval",    NULL, "10"},
 +      {"FQDNLookup",  NULL, "true"},
 +      {"Interval",    NULL, NULL},
        {"ReadThreads", NULL, "5"},
 +      {"WriteThreads", NULL, "5"},
        {"Timeout",     NULL, "2"},
        {"PreCacheChain",  NULL, "PreCache"},
        {"PostCacheChain", NULL, "PostCache"}
  };
 -static int cf_global_options_num = STATIC_ARRAY_LEN (cf_global_options);
 +static int cf_global_options_num = STATIC_ARRAY_SIZE (cf_global_options);
  
  static int cf_default_typesdb = 1;
  
@@@ -139,7 -129,6 +139,7 @@@ static int cf_dispatch (const char *typ
                const char *orig_value)
  {
        cf_callback_t *cf_cb;
 +      plugin_ctx_t old_ctx;
        char *key;
        char *value;
        int ret;
  
        ret = -1;
  
 +      old_ctx = plugin_set_ctx (cf_cb->ctx);
 +
        for (i = 0; i < cf_cb->keys_num; i++)
        {
                if ((cf_cb->keys[i] != NULL)
                }
        }
  
 +      plugin_set_ctx (old_ctx);
 +
        if (i >= cf_cb->keys_num)
                WARNING ("Plugin `%s' did not register for value `%s'.", type, key);
  
@@@ -258,12 -243,7 +258,12 @@@ static int dispatch_value_plugindir (co
  static int dispatch_loadplugin (const oconfig_item_t *ci)
  {
        int i;
 -      uint32_t flags = 0;
 +      const char *name;
 +      unsigned int flags = 0;
 +      plugin_ctx_t ctx;
 +      plugin_ctx_t old_ctx;
 +      int ret_val;
 +
        assert (strcasecmp (ci->key, "LoadPlugin") == 0);
  
        if (ci->values_num != 1)
        if (ci->values[0].type != OCONFIG_TYPE_STRING)
                return (-1);
  
 +      name = ci->values[0].value.string;
 +
 +      /* default to the global interval set before loading this plugin */
 +      memset (&ctx, 0, sizeof (ctx));
 +      ctx.interval = cf_get_default_interval ();
 +
 +      /*
 +       * XXX: Magic at work:
 +       *
 +       * Some of the language bindings, for example the Python and Perl
 +       * plugins, need to be able to export symbols to the scripts they run.
 +       * For this to happen, the "Globals" flag needs to be set.
 +       * Unfortunately, this technical detail is hard to explain to the
 +       * average user and she shouldn't have to worry about this, ideally.
 +       * So in order to save everyone's sanity use a different default for a
 +       * handful of special plugins. --octo
 +       */
 +      if ((strcasecmp ("Perl", name) == 0)
 +                      || (strcasecmp ("Python", name) == 0))
 +              flags |= PLUGIN_FLAGS_GLOBAL;
 +
        for (i = 0; i < ci->children_num; ++i) {
 -              if (ci->children[i].values_num != 1 ||
 -                              ci->children[i].values[0].type != OCONFIG_TYPE_BOOLEAN) {
 -                      WARNING("Ignoring unknown LoadPlugin option %s for plugin %s", ci->children[i].key, ci->values[0].value.string);
 -                      continue;
 +              if (strcasecmp("Globals", ci->children[i].key) == 0)
 +                      cf_util_get_flag (ci->children + i, &flags, PLUGIN_FLAGS_GLOBAL);
 +              else if (strcasecmp ("Interval", ci->children[i].key) == 0) {
 +                      double interval = 0.0;
 +
 +                      if (cf_util_get_double (ci->children + i, &interval) != 0) {
 +                              /* cf_util_get_double will log an error */
 +                              continue;
 +                      }
 +
 +                      ctx.interval = DOUBLE_TO_CDTIME_T (interval);
                }
 -              if (strcasecmp(ci->children[i].key, "globals") == 0) {
 -                      flags |= PLUGIN_FLAGS_GLOBAL;
 -              } else {
 -                      WARNING("Ignoring unknown LoadPlugin option %s for plugin %s", ci->children[i].key, ci->values[0].value.string);
 +              else {
 +                      WARNING("Ignoring unknown LoadPlugin option \"%s\" "
 +                                      "for plugin \"%s\"",
 +                                      ci->children[i].key, ci->values[0].value.string);
                }
        }
 -      return (plugin_load (ci->values[0].value.string, flags));
 +
 +      old_ctx = plugin_set_ctx (ctx);
 +      ret_val = plugin_load (name, (uint32_t) flags);
 +      /* reset to the "global" context */
 +      plugin_set_ctx (old_ctx);
 +
 +      return (ret_val);
  } /* int dispatch_value_loadplugin */
  
  static int dispatch_value_plugin (const char *plugin, oconfig_item_t *ci)
@@@ -396,18 -342,8 +396,18 @@@ static int dispatch_block_plugin (oconf
  
        /* Check for a complex callback first */
        for (cb = complex_callback_head; cb != NULL; cb = cb->next)
 +      {
                if (strcasecmp (name, cb->type) == 0)
 -                      return (cb->callback (ci));
 +              {
 +                      plugin_ctx_t old_ctx;
 +                      int ret_val;
 +
 +                      old_ctx = plugin_set_ctx (cb->ctx);
 +                      ret_val = (cb->callback (ci));
 +                      plugin_set_ctx (old_ctx);
 +                      return (ret_val);
 +              }
 +      }
  
        /* Hm, no complex plugin found. Dispatch the values one by one */
        for (i = 0; i < ci->children_num; i++)
@@@ -436,6 -372,8 +436,6 @@@ static int dispatch_block (oconfig_item
                return (dispatch_loadplugin (ci));
        else if (strcasecmp (ci->key, "Plugin") == 0)
                return (dispatch_block_plugin (ci));
 -      else if (strcasecmp (ci->key, "Threshold") == 0)
 -              return (ut_config (ci));
        else if (strcasecmp (ci->key, "Chain") == 0)
                return (fc_configure (ci));
  
@@@ -476,6 -414,12 +476,12 @@@ static int cf_ci_replace_child (oconfig
  
        /* Resize the memory containing the children to be big enough to hold
         * all children. */
+       if (dst->children_num + src->children_num - 1 == 0)
+       {
+               dst->children_num = 0;
+               return (0);
+       }
        temp = (oconfig_item_t *) realloc (dst->children,
                        sizeof (oconfig_item_t)
                        * (dst->children_num + src->children_num - 1));
@@@ -544,8 -488,7 +550,8 @@@ static int cf_ci_append_children (oconf
  } /* int cf_ci_append_children */
  
  #define CF_MAX_DEPTH 8
 -static oconfig_item_t *cf_read_generic (const char *path, int depth);
 +static oconfig_item_t *cf_read_generic (const char *path,
 +              const char *pattern, int depth);
  
  static int cf_include_all (oconfig_item_t *root, int depth)
  {
                oconfig_item_t *new;
                oconfig_item_t *old;
  
 -              /* Ignore all blocks, including `Include' blocks. */
 -              if (root->children[i].children_num != 0)
 -                      continue;
 +              char *pattern = NULL;
 +
 +              int j;
  
                if (strcasecmp (root->children[i].key, "Include") != 0)
                        continue;
                        continue;
                }
  
 -              new = cf_read_generic (old->values[0].value.string, depth + 1);
 +              for (j = 0; j < old->children_num; ++j)
 +              {
 +                      oconfig_item_t *child = old->children + j;
 +
 +                      if (strcasecmp (child->key, "Filter") == 0)
 +                              cf_util_get_string (child, &pattern);
 +                      else
 +                              ERROR ("configfile: Option `%s' not allowed in <Include> block.",
 +                                              child->key);
 +              }
 +
 +              new = cf_read_generic (old->values[0].value.string, pattern, depth + 1);
 +              sfree (pattern);
 +
                if (new == NULL)
 -                      continue;
 +                      return (-1);
  
                /* Now replace the i'th child in `root' with `new'. */
-               cf_ci_replace_child (root, new, i);
+               if (cf_ci_replace_child (root, new, i) < 0)
+                       return (-1);
  
                /* ... and go back to the new i'th child. */
                --i;
        return (0);
  } /* int cf_include_all */
  
 -static oconfig_item_t *cf_read_file (const char *file, int depth)
 +static oconfig_item_t *cf_read_file (const char *file,
 +              const char *pattern, int depth)
  {
        oconfig_item_t *root;
 +      int status;
  
        assert (depth < CF_MAX_DEPTH);
  
 +      if (pattern != NULL) {
 +#if HAVE_FNMATCH_H && HAVE_LIBGEN_H
 +              char *tmp = sstrdup (file);
 +              char *filename = basename (tmp);
 +
 +              if ((filename != NULL) && (fnmatch (pattern, filename, 0) != 0)) {
 +                      DEBUG ("configfile: Not including `%s' because it "
 +                                      "does not match pattern `%s'.",
 +                                      filename, pattern);
 +                      free (tmp);
 +                      return (NULL);
 +              }
 +
 +              free (tmp);
 +#else
 +              ERROR ("configfile: Cannot apply pattern filter '%s' "
 +                              "to file '%s': functions basename() and / or "
 +                              "fnmatch() not available.", pattern, file);
 +#endif /* HAVE_FNMATCH_H && HAVE_LIBGEN_H */
 +      }
 +
        root = oconfig_parse_file (file);
        if (root == NULL)
        {
                return (NULL);
        }
  
 -      cf_include_all (root, depth);
 +      status = cf_include_all (root, depth);
 +      if (status != 0)
 +      {
 +              oconfig_free (root);
 +              return (NULL);
 +      }
  
        return (root);
  } /* oconfig_item_t *cf_read_file */
@@@ -653,8 -556,7 +660,8 @@@ static int cf_compare_string (const voi
        return strcmp (*(const char **) p1, *(const char **) p2);
  }
  
 -static oconfig_item_t *cf_read_dir (const char *dir, int depth)
 +static oconfig_item_t *cf_read_dir (const char *dir,
 +              const char *pattern, int depth)
  {
        oconfig_item_t *root = NULL;
        DIR *dh;
                oconfig_item_t *temp;
                char *name = filenames[i];
  
 -              temp = cf_read_generic (name, depth);
 +              temp = cf_read_generic (name, pattern, depth);
                if (temp == NULL)
                {
                        /* An error should already have been reported. */
   * simpler function is used which does not do any such expansion.
   */
  #if HAVE_WORDEXP_H
 -static oconfig_item_t *cf_read_generic (const char *path, int depth)
 +static oconfig_item_t *cf_read_generic (const char *path,
 +              const char *pattern, int depth)
  {
        oconfig_item_t *root = NULL;
        int status;
                }
  
                if (S_ISREG (statbuf.st_mode))
 -                      temp = cf_read_file (path_ptr, depth);
 +                      temp = cf_read_file (path_ptr, pattern, depth);
                else if (S_ISDIR (statbuf.st_mode))
 -                      temp = cf_read_dir (path_ptr, depth);
 +                      temp = cf_read_dir (path_ptr, pattern, depth);
                else
                {
                        WARNING ("configfile: %s is neither a file nor a "
  
        wordfree (&we);
  
 -      if (root->children == NULL)
 -      {
 -              oconfig_free (root);
 -              return (NULL);
 -      }
 -
        return (root);
  } /* oconfig_item_t *cf_read_generic */
  /* #endif HAVE_WORDEXP_H */
  
  #else /* if !HAVE_WORDEXP_H */
 -static oconfig_item_t *cf_read_generic (const char *path, int depth)
 +static oconfig_item_t *cf_read_generic (const char *path,
 +              const char *pattern, int depth)
  {
        struct stat statbuf;
        int status;
        }
  
        if (S_ISREG (statbuf.st_mode))
 -              return (cf_read_file (path, depth));
 +              return (cf_read_file (path, pattern, depth));
        else if (S_ISDIR (statbuf.st_mode))
 -              return (cf_read_dir (path, depth));
 +              return (cf_read_dir (path, pattern, depth));
  
        ERROR ("configfile: %s is neither a file nor a directory.", path);
        return (NULL);
@@@ -916,29 -822,6 +923,29 @@@ const char *global_option_get (const ch
                        : cf_global_options[i].def);
  } /* char *global_option_get */
  
 +cdtime_t cf_get_default_interval (void)
 +{
 +  char const *str = global_option_get ("Interval");
 +  double interval_double = COLLECTD_DEFAULT_INTERVAL;
 +
 +  if (str != NULL)
 +  {
 +    char *endptr = NULL;
 +    double tmp = strtod (str, &endptr);
 +
 +    if ((endptr == NULL) || (endptr == str) || (*endptr != 0))
 +      ERROR ("cf_get_default_interval: Unable to parse string \"%s\" "
 +          "as number.", str);
 +    else if (tmp <= 0.0)
 +      ERROR ("cf_get_default_interval: Interval must be a positive number. "
 +          "The current number is %g.", tmp);
 +    else
 +      interval_double = tmp;
 +  }
 +
 +  return (DOUBLE_TO_CDTIME_T (interval_double));
 +} /* }}} cdtime_t cf_get_default_interval */
 +
  void cf_unregister (const char *type)
  {
        cf_callback_t *this, *prev;
@@@ -995,7 -878,6 +1002,7 @@@ void cf_register (const char *type
        cf_cb->callback = callback;
        cf_cb->keys     = keys;
        cf_cb->keys_num = keys_num;
 +      cf_cb->ctx      = plugin_get_ctx ();
  
        cf_cb->next = first_callback;
        first_callback = cf_cb;
@@@ -1019,8 -901,6 +1026,8 @@@ int cf_register_complex (const char *ty
        new->callback = callback;
        new->next = NULL;
  
 +      new->ctx = plugin_get_ctx ();
 +
        if (complex_callback_head == NULL)
        {
                complex_callback_head = new;
@@@ -1041,18 -921,12 +1048,18 @@@ int cf_read (char *filename
        oconfig_item_t *conf;
        int i;
  
 -      conf = cf_read_generic (filename, 0 /* depth */);
 +      conf = cf_read_generic (filename, /* pattern = */ NULL, /* depth = */ 0);
        if (conf == NULL)
        {
                ERROR ("Unable to read config file %s.", filename);
                return (-1);
        }
 +      else if (conf->children_num == 0)
 +      {
 +              ERROR ("Configuration file %s is empty.", filename);
 +              oconfig_free (conf);
 +              return (-1);
 +      }
  
        for (i = 0; i < conf->children_num; i++)
        {
@@@ -1135,23 -1009,6 +1142,23 @@@ int cf_util_get_int (const oconfig_item
        return (0);
  } /* }}} int cf_util_get_int */
  
 +int cf_util_get_double (const oconfig_item_t *ci, double *ret_value) /* {{{ */
 +{
 +      if ((ci == NULL) || (ret_value == NULL))
 +              return (EINVAL);
 +
 +      if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
 +      {
 +              ERROR ("cf_util_get_double: The %s option requires "
 +                              "exactly one numeric argument.", ci->key);
 +              return (-1);
 +      }
 +
 +      *ret_value = ci->values[0].value.number;
 +
 +      return (0);
 +} /* }}} int cf_util_get_double */
 +
  int cf_util_get_boolean (const oconfig_item_t *ci, _Bool *ret_bool) /* {{{ */
  {
        if ((ci == NULL) || (ret_bool == NULL))
                return (-1);
        }
  
 -      *ret_bool = ci->values[0].value.boolean ? true : false;
 +      *ret_bool = ci->values[0].value.boolean ? 1 : 0;
  
        return (0);
  } /* }}} int cf_util_get_boolean */
  
 -/* Assures that the config option is a string. The string is then converted to
 - * a port number using `service_name_to_port_number' and returned. Returns the
 - * port number in the range [1-65535] or less than zero upon failure. */
 +int cf_util_get_flag (const oconfig_item_t *ci, /* {{{ */
 +              unsigned int *ret_value, unsigned int flag)
 +{
 +      int status;
 +      _Bool b;
 +
 +      if (ret_value == NULL)
 +              return (EINVAL);
 +
 +      b = 0;
 +      status = cf_util_get_boolean (ci, &b);
 +      if (status != 0)
 +              return (status);
 +
 +      if (b)
 +      {
 +              *ret_value |= flag;
 +      }
 +      else
 +      {
 +              *ret_value &= ~flag;
 +      }
 +
 +      return (0);
 +} /* }}} int cf_util_get_flag */
 +
 +/* Assures that the config option is a string or a number if the correct range
 + * of 1-65535. The string is then converted to a port number using
 + * `service_name_to_port_number' and returned.
 + * Returns the port number in the range [1-65535] or less than zero upon
 + * failure. */
  int cf_util_get_port_number (const oconfig_item_t *ci) /* {{{ */
  {
 -      if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
 +      int tmp;
 +
 +      if ((ci->values_num != 1)
 +                      || ((ci->values[0].type != OCONFIG_TYPE_STRING)
 +                              && (ci->values[0].type != OCONFIG_TYPE_NUMBER)))
        {
 -              ERROR ("cf_util_get_port_number: The %s option requires "
 +              ERROR ("cf_util_get_port_number: The \"%s\" option requires "
                                "exactly one string argument.", ci->key);
                return (-1);
        }
  
 -      return (service_name_to_port_number (ci->values[0].value.string));
 +      if (ci->values[0].type == OCONFIG_TYPE_STRING)
 +              return (service_name_to_port_number (ci->values[0].value.string));
 +
 +      assert (ci->values[0].type == OCONFIG_TYPE_NUMBER);
 +      tmp = (int) (ci->values[0].value.number + 0.5);
 +      if ((tmp < 1) || (tmp > 65535))
 +      {
 +              ERROR ("cf_util_get_port_number: The \"%s\" option requires "
 +                              "a service name or a port number. The number "
 +                              "you specified, %i, is not in the valid "
 +                              "range of 1-65535.",
 +                              ci->key, tmp);
 +              return (-1);
 +      }
 +
 +      return (tmp);
  } /* }}} int cf_util_get_port_number */
 +
 +int cf_util_get_service (const oconfig_item_t *ci, char **ret_string) /* {{{ */
 +{
 +      int port;
 +      char *service;
 +      int status;
 +
 +      if (ci->values_num != 1)
 +      {
 +              ERROR ("cf_util_get_service: The %s option requires exactly "
 +                              "one argument.", ci->key);
 +              return (-1);
 +      }
 +
 +      if (ci->values[0].type == OCONFIG_TYPE_STRING)
 +              return (cf_util_get_string (ci, ret_string));
 +      if (ci->values[0].type != OCONFIG_TYPE_NUMBER)
 +      {
 +              ERROR ("cf_util_get_service: The %s option requires "
 +                              "exactly one string or numeric argument.",
 +                              ci->key);
 +      }
 +
 +      port = 0;
 +      status = cf_util_get_int (ci, &port);
 +      if (status != 0)
 +              return (status);
 +      else if ((port < 1) || (port > 65535))
 +      {
 +              ERROR ("cf_util_get_service: The port number given "
 +                              "for the %s option is out of "
 +                              "range (%i).", ci->key, port);
 +              return (-1);
 +      }
 +
 +      service = malloc (6);
 +      if (service == NULL)
 +      {
 +              ERROR ("cf_util_get_service: Out of memory.");
 +              return (-1);
 +      }
 +      ssnprintf (service, 6, "%i", port);
 +
 +      sfree (*ret_string);
 +      *ret_string = service;
 +
 +      return (0);
 +} /* }}} int cf_util_get_service */
 +
 +int cf_util_get_cdtime (const oconfig_item_t *ci, cdtime_t *ret_value) /* {{{ */
 +{
 +      if ((ci == NULL) || (ret_value == NULL))
 +              return (EINVAL);
 +
 +      if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
 +      {
 +              ERROR ("cf_util_get_cdtime: The %s option requires "
 +                              "exactly one numeric argument.", ci->key);
 +              return (-1);
 +      }
 +
 +      if (ci->values[0].value.number < 0.0)
 +      {
 +              ERROR ("cf_util_get_cdtime: The numeric argument of the %s "
 +                              "option must not be negative.", ci->key);
 +              return (-1);
 +      }
 +
 +      *ret_value = DOUBLE_TO_CDTIME_T (ci->values[0].value.number);
 +
 +      return (0);
 +} /* }}} int cf_util_get_cdtime */
 +
diff --combined src/curl.c
@@@ -60,8 -60,6 +60,8 @@@ struct web_page_s /* {{{ *
    int   verify_peer;
    int   verify_host;
    char *cacert;
 +  struct curl_slist *headers;
 +  char *post_body;
    int   response_time;
  
    CURL *curl;
@@@ -150,8 -148,6 +150,8 @@@ static void cc_web_page_free (web_page_
    sfree (wp->pass);
    sfree (wp->credentials);
    sfree (wp->cacert);
 +  sfree (wp->post_body);
 +  curl_slist_free_all (wp->headers);
  
    sfree (wp->buffer);
  
@@@ -177,23 -173,6 +177,23 @@@ static int cc_config_add_string (const 
    return (0);
  } /* }}} int cc_config_add_string */
  
 +static int cc_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
 +    oconfig_item_t *ci)
 +{
 +  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
 +  {
 +    WARNING ("curl plugin: `%s' needs exactly one string argument.", name);
 +    return (-1);
 +  }
 +
 +  *dest = curl_slist_append(*dest, ci->values[0].value.string);
 +  if (*dest == NULL)
 +    return (-1);
 +
 +  return (0);
 +} /* }}} int cc_config_append_string */
 +
 +
  static int cc_config_set_boolean (const char *name, int *dest, /* {{{ */
      oconfig_item_t *ci)
  {
@@@ -426,10 -405,6 +426,10 @@@ static int cc_page_init_curl (web_page_
        wp->verify_host ? 2L : 0L);
    if (wp->cacert != NULL)
      curl_easy_setopt (wp->curl, CURLOPT_CAINFO, wp->cacert);
 +  if (wp->headers != NULL)
 +    curl_easy_setopt (wp->curl, CURLOPT_HTTPHEADER, wp->headers);
 +  if (wp->post_body != NULL)
 +    curl_easy_setopt (wp->curl, CURLOPT_POSTFIELDS, wp->post_body);
  
    return (0);
  } /* }}} int cc_page_init_curl */
@@@ -491,10 -466,6 +491,10 @@@ static int cc_config_add_page (oconfig_
      else if (strcasecmp ("Match", child->key) == 0)
        /* Be liberal with failing matches => don't set `status'. */
        cc_config_add_match (page, child);
 +    else if (strcasecmp ("Header", child->key) == 0)
 +      status = cc_config_append_string ("Header", &page->headers, child);
 +    else if (strcasecmp ("Post", child->key) == 0)
 +      status = cc_config_add_string ("Post", &page->post_body, child);
      else
      {
        WARNING ("curl plugin: Option `%s' not allowed here.", child->key);
@@@ -595,6 -566,7 +595,7 @@@ static int cc_init (void) /* {{{ *
      INFO ("curl plugin: No pages have been defined.");
      return (-1);
    }
+   curl_global_init (CURL_GLOBAL_SSL);
    return (0);
  } /* }}} int cc_init */
  
@@@ -608,12 -580,12 +609,12 @@@ static void cc_submit (const web_page_
  
    vl.values = values;
    vl.values_len = 1;
 -  vl.time = time (NULL);
    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
    sstrncpy (vl.plugin, "curl", sizeof (vl.plugin));
    sstrncpy (vl.plugin_instance, wp->instance, sizeof (vl.plugin_instance));
    sstrncpy (vl.type, wm->type, sizeof (vl.type));
 -  sstrncpy (vl.type_instance, wm->instance, sizeof (vl.type_instance));
 +  if (wm->instance != NULL)
 +    sstrncpy (vl.type_instance, wm->instance, sizeof (vl.type_instance));
  
    plugin_dispatch_values (&vl);
  } /* }}} void cc_submit */
@@@ -627,6 -599,7 +628,6 @@@ static void cc_submit_response_time (co
  
    vl.values = values;
    vl.values_len = 1;
 -  vl.time = time (NULL);
    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
    sstrncpy (vl.plugin, "curl", sizeof (vl.plugin));
    sstrncpy (vl.plugin_instance, wp->instance, sizeof (vl.plugin_instance));
diff --combined src/curl_json.c
@@@ -40,7 -40,7 +40,7 @@@
  
  #define CJ_DEFAULT_HOST "localhost"
  #define CJ_KEY_MAGIC 0x43484b59UL /* CHKY */
 -#define CJ_IS_KEY(key) (key)->magic == CJ_KEY_MAGIC
 +#define CJ_IS_KEY(key) ((key)->magic == CJ_KEY_MAGIC)
  #define CJ_ANY "*"
  #define COUCH_MIN(x,y) ((x) < (y) ? (x) : (y))
  
@@@ -48,10 -48,10 +48,10 @@@ struct cj_key_s
  typedef struct cj_key_s cj_key_t;
  struct cj_key_s /* {{{ */
  {
 +  unsigned long magic;
    char *path;
    char *type;
    char *instance;
 -  unsigned long magic;
  };
  /* }}} */
  
@@@ -64,11 -64,9 +64,11 @@@ struct cj_s /* {{{ *
    char *user;
    char *pass;
    char *credentials;
 -  int   verify_peer;
 -  int   verify_host;
 +  _Bool verify_peer;
 +  _Bool verify_host;
    char *cacert;
 +  struct curl_slist *headers;
 +  char *post_body;
  
    CURL *curl;
    char curl_errbuf[CURL_ERROR_SIZE];
@@@ -124,8 -122,7 +124,8 @@@ static size_t cj_curl_callback (void *b
    if (status != yajl_status_ok)
    {
      unsigned char *msg =
 -      yajl_get_error(db->yajl, 1, (unsigned char *)buf, len);
 +      yajl_get_error(db->yajl, /* verbose = */ 1,
 +          /* jsonText = */ (unsigned char *) buf, (unsigned int) len);
      ERROR ("curl_json plugin: yajl_parse failed: %s", msg);
      yajl_free_error(db->yajl, msg);
      return (0); /* abort write callback */
@@@ -180,21 -177,41 +180,21 @@@ static int cj_cb_number (void *ctx
  
    cj_t *db = (cj_t *)ctx;
    cj_key_t *key = db->state[db->depth].key;
 -  char *endptr;
    value_t vt;
    int type;
 +  int status;
  
 -  if (key == NULL)
 +  if ((key == NULL) || !CJ_IS_KEY (key))
      return (CJ_CB_CONTINUE);
  
    memcpy (buffer, number, number_len);
    buffer[sizeof (buffer) - 1] = 0;
  
    type = cj_get_type (key);
 -  if (type < 0)
 -    return (CJ_CB_CONTINUE);
 -
 -  endptr = NULL;
 -  errno = 0;
 -
 -  if (type == DS_TYPE_COUNTER)
 -    vt.counter = (counter_t) strtoull (buffer, &endptr, /* base = */ 0);
 -  else if (type == DS_TYPE_GAUGE)
 -    vt.gauge = (gauge_t) strtod (buffer, &endptr);
 -  else if (type == DS_TYPE_DERIVE)
 -    vt.derive = (derive_t) strtoll (buffer, &endptr, /* base = */ 0);
 -  else if (type == DS_TYPE_ABSOLUTE)
 -    vt.absolute = (absolute_t) strtoull (buffer, &endptr, /* base = */ 0);
 -  else
 +  status = parse_value (buffer, &vt, type);
 +  if (status != 0)
    {
 -    ERROR ("curl_json plugin: Unknown data source type: \"%s\"", key->type);
 -    return (CJ_CB_ABORT);
 -  }
 -
 -  if ((endptr == &buffer[0]) || (errno != 0))
 -  {
 -    NOTICE ("curl_json plugin: Overflow while parsing number. "
 -        "Ignoring this value.");
 +    NOTICE ("curl_json plugin: Unable to parse number: \"%s\"", buffer);
      return (CJ_CB_CONTINUE);
    }
  
@@@ -234,26 -251,34 +234,26 @@@ static int cj_cb_string (void *ctx, con
      yajl_len_t len)
  {
    cj_t *db = (cj_t *)ctx;
 -  c_avl_tree_t *tree;
 -  char *ptr;
 +  char str[len + 1];
  
 -  if (db->depth != 1) /* e.g. _all_dbs */
 -    return (CJ_CB_CONTINUE);
 +  /* Create a null-terminated version of the string. */
 +  memcpy (str, val, len);
 +  str[len] = 0;
  
 -  cj_cb_map_key (ctx, val, len); /* same logic */
 -
 -  tree = db->state[db->depth].tree;
 +  /* No configuration for this string -> simply return. */
 +  if (db->state[db->depth].key == NULL)
 +    return (CJ_CB_CONTINUE);
  
 -  if ((tree != NULL) && (ptr = rindex (db->url, '/')))
 +  if (!CJ_IS_KEY (db->state[db->depth].key))
    {
 -    char url[PATH_MAX];
 -    CURL *curl;
 -
 -    /* url =~ s,[^/]+$,$name, */
 -    len = (ptr - db->url) + 1;
 -    ptr = url;
 -    sstrncpy (ptr, db->url, sizeof (url));
 -    sstrncpy (ptr + len, db->state[db->depth].name, sizeof (url) - len);
 -
 -    curl = curl_easy_duphandle (db->curl);
 -    curl_easy_setopt (curl, CURLOPT_URL, url);
 -    cj_curl_perform (db, curl);
 -    curl_easy_cleanup (curl);
 +    NOTICE ("curl_json plugin: Found string \"%s\", but the configuration "
 +        "expects a map here.", str);
 +    return (CJ_CB_CONTINUE);
    }
 -  return (CJ_CB_CONTINUE);
 -}
 +
 +  /* Handle the string as if it was a number. */
 +  return (cj_cb_number (ctx, (const char *) val, len));
 +} /* int cj_cb_string */
  
  static int cj_cb_start (void *ctx)
  {
@@@ -369,21 -394,14 +369,21 @@@ static void cj_free (void *arg) /* {{{ 
    sfree (db->pass);
    sfree (db->credentials);
    sfree (db->cacert);
 +  sfree (db->post_body);
 +  curl_slist_free_all (db->headers);
  
    sfree (db);
  } /* }}} void cj_free */
  
  /* Configuration handling functions {{{ */
  
 -static int cj_config_add_string (const char *name, char **dest, /* {{{ */
 -                                      oconfig_item_t *ci)
 +static c_avl_tree_t *cj_avl_create(void)
 +{
 +  return c_avl_create ((int (*) (const void *, const void *)) strcmp);
 +}
 +
 +static int cj_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
 +    oconfig_item_t *ci)
  {
    if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
    {
      return (-1);
    }
  
 -  sfree (*dest);
 -  *dest = strdup (ci->values[0].value.string);
 +  *dest = curl_slist_append(*dest, ci->values[0].value.string);
    if (*dest == NULL)
      return (-1);
  
    return (0);
 -} /* }}} int cj_config_add_string */
 -
 -static int cj_config_set_boolean (const char *name, int *dest, /* {{{ */
 -                                       oconfig_item_t *ci)
 -{
 -  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
 -  {
 -    WARNING ("curl_json plugin: `%s' needs exactly one boolean argument.", name);
 -    return (-1);
 -  }
 -
 -  *dest = ci->values[0].value.boolean ? 1 : 0;
 -
 -  return (0);
 -} /* }}} int cj_config_set_boolean */
 -
 -static c_avl_tree_t *cj_avl_create(void)
 -{
 -  return c_avl_create ((int (*) (const void *, const void *)) strcmp);
 -}
 +} /* }}} int cj_config_append_string */
  
  static int cj_config_add_key (cj_t *db, /* {{{ */
                                     oconfig_item_t *ci)
  
    if (strcasecmp ("Key", ci->key) == 0)
    {
 -    status = cj_config_add_string ("Key", &key->path, ci);
 +    status = cf_util_get_string (ci, &key->path);
      if (status != 0)
      {
        sfree (key);
      oconfig_item_t *child = ci->children + i;
  
      if (strcasecmp ("Type", child->key) == 0)
 -      status = cj_config_add_string ("Type", &key->type, child);
 +      status = cf_util_get_string (child, &key->type);
      else if (strcasecmp ("Instance", child->key) == 0)
 -      status = cj_config_add_string ("Instance", &key->instance, child);
 +      status = cf_util_get_string (child, &key->instance);
      else
      {
        WARNING ("curl_json plugin: Option `%s' not allowed here.", child->key);
          len = ptr-name;
          if (len == 0)
            break;
 +        len = COUCH_MIN(len, sizeof (ent)-1);
          sstrncpy (ent, name, len+1);
  
          if (c_avl_get (tree, ent, (void *) &value) != 0)
@@@ -568,10 -605,6 +568,10 @@@ static int cj_init_curl (cj_t *db) /* {
                      db->verify_host ? 2L : 0L);
    if (db->cacert != NULL)
      curl_easy_setopt (db->curl, CURLOPT_CAINFO, db->cacert);
 +  if (db->headers != NULL)
 +    curl_easy_setopt (db->curl, CURLOPT_HTTPHEADER, db->headers);
 +  if (db->post_body != NULL)
 +    curl_easy_setopt (db->curl, CURLOPT_POSTFIELDS, db->post_body);
  
    return (0);
  } /* }}} int cj_init_curl */
@@@ -600,7 -633,7 +600,7 @@@ static int cj_config_add_url (oconfig_i
  
    if (strcasecmp ("URL", ci->key) == 0)
    {
 -    status = cj_config_add_string ("URL", &db->url, ci);
 +    status = cf_util_get_string (ci, &db->url);
      if (status != 0)
      {
        sfree (db);
      oconfig_item_t *child = ci->children + i;
  
      if (strcasecmp ("Instance", child->key) == 0)
 -      status = cj_config_add_string ("Instance", &db->instance, child);
 +      status = cf_util_get_string (child, &db->instance);
      else if (strcasecmp ("Host", child->key) == 0)
 -      status = cj_config_add_string ("Host", &db->host, child);
 +      status = cf_util_get_string (child, &db->host);
      else if (strcasecmp ("User", child->key) == 0)
 -      status = cj_config_add_string ("User", &db->user, child);
 +      status = cf_util_get_string (child, &db->user);
      else if (strcasecmp ("Password", child->key) == 0)
 -      status = cj_config_add_string ("Password", &db->pass, child);
 +      status = cf_util_get_string (child, &db->pass);
      else if (strcasecmp ("VerifyPeer", child->key) == 0)
 -      status = cj_config_set_boolean ("VerifyPeer", &db->verify_peer, child);
 +      status = cf_util_get_boolean (child, &db->verify_peer);
      else if (strcasecmp ("VerifyHost", child->key) == 0)
 -      status = cj_config_set_boolean ("VerifyHost", &db->verify_host, child);
 +      status = cf_util_get_boolean (child, &db->verify_host);
      else if (strcasecmp ("CACert", child->key) == 0)
 -      status = cj_config_add_string ("CACert", &db->cacert, child);
 +      status = cf_util_get_string (child, &db->cacert);
 +    else if (strcasecmp ("Header", child->key) == 0)
 +      status = cj_config_append_string ("Header", &db->headers, child);
 +    else if (strcasecmp ("Post", child->key) == 0)
 +      status = cf_util_get_string (child, &db->post_body);
      else if (strcasecmp ("Key", child->key) == 0)
        status = cj_config_add_key (db, child);
      else
@@@ -788,52 -817,48 +788,52 @@@ static int cj_curl_perform (cj_t *db, C
      return (-1);
    }
  
 +  url = NULL;
 +  curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
 +
    status = curl_easy_perform (curl);
    if (status != CURLE_OK)
    {
      ERROR ("curl_json plugin: curl_easy_perform failed with status %i: %s (%s)",
 -           status, db->curl_errbuf, url);
 +           status, db->curl_errbuf, (url != NULL) ? url : "<null>");
      yajl_free (db->yajl);
      db->yajl = yprev;
      return (-1);
    }
  
 -  curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rc);
  
    /* The response code is zero if a non-HTTP transport was used. */
    if ((rc != 0) && (rc != 200))
    {
 -    ERROR ("curl_json plugin: curl_easy_perform failed with response code %ld (%s)",
 -           rc, url);
 +    ERROR ("curl_json plugin: curl_easy_perform failed with "
 +        "response code %ld (%s)", rc, url);
      yajl_free (db->yajl);
      db->yajl = yprev;
      return (-1);
    }
  
  #if HAVE_YAJL_V2
 -  status = yajl_complete_parse(db->yajl);
 +    status = yajl_complete_parse(db->yajl);
  #else
 -  status = yajl_parse_complete(db->yajl);
 +    status = yajl_parse_complete(db->yajl);
  #endif
    if (status != yajl_status_ok)
    {
 -    ERROR ("curl_json plugin: %s failed with status %i.",
 -#if HAVE_YAJL_V2
 -        "yajl_complete_parse",
 -#else
 -        "yajl_parse_complete",
 -#endif
 -        status);
 +    unsigned char *errmsg;
 +
 +    errmsg = yajl_get_error (db->yajl, /* verbose = */ 0,
 +        /* jsonText = */ NULL, /* jsonTextLen = */ 0);
 +    ERROR ("curl_json plugin: yajl_parse_complete failed: %s",
 +        (char *) errmsg);
 +    yajl_free_error (db->yajl, errmsg);
 +    yajl_free (db->yajl);
 +    db->yajl = yprev;
 +    return (-1);
    }
  
    yajl_free (db->yajl);
    db->yajl = yprev;
 -
    return (0);
  } /* }}} int cj_curl_perform */
  
@@@ -857,9 -882,18 +857,18 @@@ static int cj_read (user_data_t *ud) /
    return cj_curl_perform (db, db->curl);
  } /* }}} int cj_read */
  
+ static int cj_init (void) /* {{{ */
+ {
+   /* Call this while collectd is still single-threaded to avoid
+    * initialization issues in libgcrypt. */
+   curl_global_init (CURL_GLOBAL_SSL);
+   return (0);
+ } /* }}} int cj_init */
  void module_register (void)
  {
    plugin_register_complex_config ("curl_json", cj_config);
+   plugin_register_init ("curl_json", cj_init);
  } /* void module_register */
  
  /* vim: set sw=2 sts=2 et fdm=marker : */
diff --combined src/curl_xml.c
@@@ -28,7 -28,6 +28,7 @@@
  #include <libxml/parser.h>
  #include <libxml/tree.h>
  #include <libxml/xpath.h>
 +#include <libxml/xpathInternals.h>
  
  #include <curl/curl.h>
  
@@@ -59,14 -58,6 +59,14 @@@ struct cx_xpath_s /* {{{ *
  typedef struct cx_xpath_s cx_xpath_t;
  /* }}} */
  
 +struct cx_namespace_s /* {{{ */
 +{
 +  char *prefix;
 +  char *url;
 +};
 +typedef struct cx_namespace_s cx_namespace_t;
 +/* }}} */
 +
  struct cx_s /* {{{ */
  {
    char *instance;
    _Bool verify_peer;
    _Bool verify_host;
    char *cacert;
 +  char *post_body;
 +  struct curl_slist *headers;
 +
 +  cx_namespace_t *namespaces;
 +  size_t namespaces_num;
  
    CURL *curl;
    char curl_errbuf[CURL_ERROR_SIZE];
@@@ -174,7 -160,6 +174,7 @@@ static void cx_list_free (llist_t *list
  static void cx_free (void *arg) /* {{{ */
  {
    cx_t *db;
 +  size_t i;
  
    DEBUG ("curl_xml plugin: cx_free (arg = %p);", arg);
  
    sfree (db->pass);
    sfree (db->credentials);
    sfree (db->cacert);
 +  sfree (db->post_body);
 +  curl_slist_free_all (db->headers);
 +
 +  for (i = 0; i < db->namespaces_num; i++)
 +  {
 +    sfree (db->namespaces[i].prefix);
 +    sfree (db->namespaces[i].url);
 +  }
 +  sfree (db->namespaces);
  
    sfree (db);
  } /* }}} void cx_free */
  
 +static int cx_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
 +    oconfig_item_t *ci)
 +{
 +  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
 +  {
 +    WARNING ("curl_xml plugin: `%s' needs exactly one string argument.", name);
 +    return (-1);
 +  }
 +
 +  *dest = curl_slist_append(*dest, ci->values[0].value.string);
 +  if (*dest == NULL)
 +    return (-1);
 +
 +  return (0);
 +} /* }}} int cx_config_append_string */
 +
  static int cx_check_type (const data_set_t *ds, cx_xpath_t *xpath) /* {{{ */
  {
    if (!ds)
@@@ -265,8 -225,7 +265,8 @@@ static xmlXPathObjectPtr cx_evaluate_xp
  
  static int cx_if_not_text_node (xmlNodePtr node) /* {{{ */
  {
 -  if (node->type == XML_TEXT_NODE || node->type == XML_ATTRIBUTE_NODE)
 +  if (node->type == XML_TEXT_NODE || node->type == XML_ATTRIBUTE_NODE ||
 +      node->type == XML_ELEMENT_NODE)
      return (0);
  
    WARNING ("curl_xml plugin: "
@@@ -383,9 -342,9 +383,9 @@@ static int cx_handle_instance_xpath (xm
    memset (vl->type_instance, 0, sizeof (vl->type_instance));
  
    /* If the base xpath returns more than one block, the result is assumed to be
 -   * a table. The `Instnce' option is not optional in this case. Check for the
 +   * a table. The `Instance' option is not optional in this case. Check for the
     * condition and inform the user. */
-   if (is_table && (vl->type_instance == NULL))
+   if (is_table)
    {
      WARNING ("curl_xml plugin: "
          "Base-XPath %s is a table (more than one result was returned), "
@@@ -561,7 -520,6 +561,7 @@@ static int cx_parse_stats_xml(xmlChar* 
    int status;
    xmlDocPtr doc;
    xmlXPathContextPtr xpath_ctx;
 +  size_t i;
  
    /* Load the XML */
    doc = xmlParseDoc(xml);
      return (-1);
    }
  
 +  for (i = 0; i < db->namespaces_num; i++)
 +  {
 +    cx_namespace_t const *ns = db->namespaces + i;
 +    status = xmlXPathRegisterNs (xpath_ctx,
 +        BAD_CAST ns->prefix, BAD_CAST ns->url);
 +    if (status != 0)
 +    {
 +      ERROR ("curl_xml plugin: "
 +          "unable to register NS with prefix=\"%s\" and href=\"%s\"\n",
 +          ns->prefix, ns->url);
 +      xmlXPathFreeContext(xpath_ctx);
 +      xmlFreeDoc (doc);
 +      return (status);
 +    }
 +  }
 +
    status = cx_handle_parsed_xml (doc, xpath_ctx, db);
    /* Cleanup */
    xmlXPathFreeContext(xpath_ctx);
@@@ -785,46 -727,6 +785,46 @@@ static int cx_config_add_xpath (cx_t *d
    return (status);
  } /* }}} int cx_config_add_xpath */
  
 +static int cx_config_add_namespace (cx_t *db, /* {{{ */
 +    oconfig_item_t *ci)
 +{
 +  cx_namespace_t *ns;
 +
 +  if ((ci->values_num != 2)
 +      || (ci->values[0].type != OCONFIG_TYPE_STRING)
 +      || (ci->values[1].type != OCONFIG_TYPE_STRING))
 +  {
 +    WARNING ("curl_xml plugin: The `Namespace' option "
 +             "needs exactly two string arguments.");
 +    return (EINVAL);
 +  }
 +
 +  ns = realloc (db->namespaces, sizeof (*db->namespaces)
 +      * (db->namespaces_num + 1));
 +  if (ns == NULL)
 +  {
 +    ERROR ("curl_xml plugin: realloc failed.");
 +    return (ENOMEM);
 +  }
 +  db->namespaces = ns;
 +  ns = db->namespaces + db->namespaces_num;
 +  memset (ns, 0, sizeof (*ns));
 +
 +  ns->prefix = strdup (ci->values[0].value.string);
 +  ns->url = strdup (ci->values[1].value.string);
 +
 +  if ((ns->prefix == NULL) || (ns->url == NULL))
 +  {
 +    sfree (ns->prefix);
 +    sfree (ns->url);
 +    ERROR ("curl_xml plugin: strdup failed.");
 +    return (ENOMEM);
 +  }
 +
 +  db->namespaces_num++;
 +  return (0);
 +} /* }}} int cx_config_add_namespace */
 +
  /* Initialize db->curl */
  static int cx_init_curl (cx_t *db) /* {{{ */
  {
                      db->verify_host ? 2L : 0L);
    if (db->cacert != NULL)
      curl_easy_setopt (db->curl, CURLOPT_CAINFO, db->cacert);
 +  if (db->headers != NULL)
 +    curl_easy_setopt (db->curl, CURLOPT_HTTPHEADER, db->headers);
 +  if (db->post_body != NULL)
 +    curl_easy_setopt (db->curl, CURLOPT_POSTFIELDS, db->post_body);
  
    return (0);
  } /* }}} int cx_init_curl */
@@@ -935,12 -833,6 +935,12 @@@ static int cx_config_add_url (oconfig_i
        status = cf_util_get_string (child, &db->cacert);
      else if (strcasecmp ("xpath", child->key) == 0)
        status = cx_config_add_xpath (db, child);
 +    else if (strcasecmp ("Header", child->key) == 0)
 +      status = cx_config_append_string ("Header", &db->headers, child);
 +    else if (strcasecmp ("Post", child->key) == 0)
 +      status = cf_util_get_string (child, &db->post_body);
 +    else if (strcasecmp ("Namespace", child->key) == 0)
 +      status = cx_config_add_namespace (db, child);
      else
      {
        WARNING ("curl_xml plugin: Option `%s' not allowed here.", child->key);
@@@ -1034,9 -926,18 +1034,18 @@@ static int cx_config (oconfig_item_t *c
    return (0);
  } /* }}} int cx_config */
  
+ static int cx_init (void) /* {{{ */
+ {
+   /* Call this while collectd is still single-threaded to avoid
+    * initialization issues in libgcrypt. */
+   curl_global_init (CURL_GLOBAL_SSL);
+   return (0);
+ } /* }}} int cx_init */
  void module_register (void)
  {
    plugin_register_complex_config ("curl_xml", cx_config);
+   plugin_register_init ("curl_xml", cx_init);
  } /* void module_register */
  
  /* vim: set sw=2 sts=2 et fdm=marker : */
diff --combined src/snmp.c
@@@ -69,7 -69,7 +69,7 @@@ struct host_definition_
    int version;
    void *sess_handle;
    c_complain_t complaint;
 -  uint32_t interval;
 +  cdtime_t interval;
    data_definition_t **data_list;
    int data_list_len;
  };
@@@ -108,7 -108,7 +108,7 @@@ static int csnmp_read_host (user_data_
   */
  static void csnmp_oid_init (oid_t *dst, oid const *src, size_t n)
  {
 -  assert (n <= STATIC_ARRAY_LEN (dst->oid));
 +  assert (n <= STATIC_ARRAY_SIZE (dst->oid));
    memcpy (dst->oid, src, sizeof (*src) * n);
    dst->oid_len = n;
  }
@@@ -207,6 -207,7 +207,6 @@@ static void csnmp_host_definition_destr
   *      +-> csnmp_config_add_host_community
   *      +-> csnmp_config_add_host_version
   *      +-> csnmp_config_add_host_collect
 - *      +-> csnmp_config_add_host_interval
   */
  static void call_snmp_init_once (void)
  {
@@@ -590,6 -591,22 +590,6 @@@ static int csnmp_config_add_host_collec
    return (0);
  } /* int csnmp_config_add_host_collect */
  
 -static int csnmp_config_add_host_interval (host_definition_t *hd, oconfig_item_t *ci)
 -{
 -  if ((ci->values_num != 1)
 -      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
 -  {
 -    WARNING ("snmp plugin: The `Interval' config option needs exactly one number argument.");
 -    return (-1);
 -  }
 -
 -  hd->interval = ci->values[0].value.number >= 0
 -    ? (uint32_t) ci->values[0].value.number
 -    : 0;
 -
 -  return (0);
 -} /* int csnmp_config_add_host_interval */
 -
  static int csnmp_config_add_host (oconfig_item_t *ci)
  {
    host_definition_t *hd;
      else if (strcasecmp ("Collect", option->key) == 0)
        csnmp_config_add_host_collect (hd, option);
      else if (strcasecmp ("Interval", option->key) == 0)
 -      csnmp_config_add_host_interval (hd, option);
 +      cf_util_get_cdtime (option, &hd->interval);
      else
      {
        WARNING ("snmp plugin: csnmp_config_add_host: Option `%s' not allowed here.", option->key);
    cb_data.data = hd;
    cb_data.free_func = csnmp_host_definition_destroy;
  
 -  memset (&cb_interval, 0, sizeof (cb_interval));
 -  if (hd->interval != 0)
 -    cb_interval.tv_sec = (time_t) hd->interval;
 +  CDTIME_T_TO_TIMESPEC (hd->interval, &cb_interval);
  
    status = plugin_register_complex_read (/* group = */ NULL, cb_name,
        csnmp_read_host, /* interval = */ &cb_interval,
@@@ -751,8 -770,7 +751,8 @@@ static void csnmp_host_open_session (ho
  
  /* TODO: Check if negative values wrap around. Problem: negative temperatures. */
  static value_t csnmp_value_list_to_value (struct variable_list *vl, int type,
 -    double scale, double shift)
 +    double scale, double shift,
 +    const char *host_name, const char *data_name)
  {
    value_t ret;
    uint64_t tmp_unsigned = 0;
            oid_buffer);
      else
  #endif
 -      WARNING ("snmp plugin: I don't know the ASN type \"%i\" (OID: %s)",
 -          (int) vl->type, oid_buffer);
 +      WARNING ("snmp plugin: I don't know the ASN type #%i "
 +               "(OID: \"%s\", data block \"%s\", host block \"%s\")",
 +          (int) vl->type, oid_buffer,
 +          (data_name != NULL) ? data_name : "UNKNOWN",
 +          (host_name != NULL) ? host_name : "UNKNOWN");
  
      defined = 0;
    }
    return (ret);
  } /* value_t csnmp_value_list_to_value */
  
 -/* Returns true if all OIDs have left their subtree */
 -static int csnmp_check_res_left_subtree (const host_definition_t *host,
 -    const data_definition_t *data,
 -    struct snmp_pdu *res)
 -{
 -  struct variable_list *vb;
 -  int num_checked;
 -  int num_left_subtree;
 -  int i;
 -
 -  vb = res->variables;
 -  if (vb == NULL)
 -    return (-1);
 -
 -  num_checked = 0;
 -  num_left_subtree = 0;
 -
 -  /* check all the variables and count how many have left their subtree */
 -  for (vb = res->variables, i = 0;
 -      (vb != NULL) && (i < data->values_len);
 -      vb = vb->next_variable, i++)
 -  {
 -    num_checked++;
 -
 -    if ((vb->type == SNMP_ENDOFMIBVIEW)
 -        || (snmp_oid_ncompare (data->values[i].oid,
 -            data->values[i].oid_len,
 -            vb->name, vb->name_length,
 -            data->values[i].oid_len) != 0))
 -      num_left_subtree++;
 -  }
 -
 -  /* check if enough variables have been returned */
 -  if (i < data->values_len)
 -  {
 -    ERROR ("snmp plugin: host %s: Expected %i variables, but got only %i",
 -        host->name, data->values_len, i);
 -    return (-1);
 -  }
 -
 -  if (data->instance.oid.oid_len > 0)
 -  {
 -    if (vb == NULL)
 -    {
 -      ERROR ("snmp plugin: host %s: Expected one more variable for "
 -          "the instance..", host->name);
 -      return (-1);
 -    }
 -
 -    num_checked++;
 -    if (snmp_oid_ncompare (data->instance.oid.oid,
 -          data->instance.oid.oid_len,
 -          vb->name, vb->name_length,
 -          data->instance.oid.oid_len) != 0)
 -      num_left_subtree++;
 -  }
 -
 -  DEBUG ("snmp plugin: csnmp_check_res_left_subtree: %i of %i variables have "
 -      "left their subtree",
 -      num_left_subtree, num_checked);
 -  if (num_left_subtree >= num_checked)
 -    return (1);
 -  return (0);
 -} /* int csnmp_check_res_left_subtree */
 -
  static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */
      const struct variable_list *vb, size_t dst_size)
  {
@@@ -964,8 -1044,8 +964,8 @@@ static int csnmp_strvbcopy (char *dst, 
  
  static int csnmp_instance_list_add (csnmp_list_instances_t **head,
      csnmp_list_instances_t **tail,
 -    struct snmp_pdu const *res,
 -    oid_t const *root)
 +    const struct snmp_pdu *res,
 +    const host_definition_t *hd, const data_definition_t *dd)
  {
    csnmp_list_instances_t *il;
    struct variable_list *vb;
    memset (il, 0, sizeof (*il));
    il->next = NULL;
  
 -  status = csnmp_oid_suffix (&il->suffix, &vb_name, root);
 +  status = csnmp_oid_suffix (&il->suffix, &vb_name, &dd->instance.oid);
    if (status != 0)
    {
      sfree (il);
    }
    else
    {
 -    value_t val = csnmp_value_list_to_value (vb, DS_TYPE_COUNTER, 1.0, 0.0);
 +    value_t val = csnmp_value_list_to_value (vb, DS_TYPE_COUNTER,
 +        /* scale = */ 1.0, /* shift = */ 0.0, hd->name, dd->name);
      ssnprintf (il->instance, sizeof (il->instance),
          "%llu", val.counter);
    }
@@@ -1199,18 -1278,11 +1199,18 @@@ static int csnmp_read_table (host_defin
    struct variable_list *vb;
  
    const data_set_t *ds;
 -  oid_t *oid_list;
 -  uint32_t oid_list_len;
 +
 +  uint32_t oid_list_len = (uint32_t) (data->values_len + 1);
 +  /* Holds the last OID returned by the device. We use this in the GETNEXT
 +   * request to proceed. */
 +  oid_t oid_list[oid_list_len];
 +  /* Set to false when an OID has left its subtree so we don't re-request it
 +   * again. */
 +  _Bool oid_list_todo[oid_list_len];
  
    int status;
    int i;
 +  uint32_t j;
  
    /* `value_list_head' and `value_list_tail' implement a linked list for each
     * value. `instance_list_head' and `instance_list_tail' implement a linked list of
    }
  
    /* We need a copy of all the OIDs, because GETNEXT will destroy them. */
 -  oid_list_len = data->values_len + 1;
 -  oid_list = (oid_t *) malloc (sizeof (oid_t) * (oid_list_len));
 -  if (oid_list == NULL)
 -  {
 -    ERROR ("snmp plugin: csnmp_read_table: malloc failed.");
 -    return (-1);
 -  }
    memcpy (oid_list, data->values, data->values_len * sizeof (oid_t));
    if (data->instance.oid.oid_len > 0)
      memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t));
 -  else
 +  else /* no InstanceFrom option specified. */
      oid_list_len--;
  
 +  for (j = 0; j < oid_list_len; j++)
 +    oid_list_todo[j] = 1;
 +
    /* We're going to construct n linked lists, one for each "value".
     * value_list_head will contain pointers to the heads of these linked lists,
     * value_list_tail will contain pointers to the tail of the lists. */
    if ((value_list_head == NULL) || (value_list_tail == NULL))
    {
      ERROR ("snmp plugin: csnmp_read_table: calloc failed.");
 -    sfree (oid_list);
      sfree (value_list_head);
      sfree (value_list_tail);
      return (-1);
    status = 0;
    while (status == 0)
    {
 +    int oid_list_todo_num;
 +
      req = snmp_pdu_create (SNMP_MSG_GETNEXT);
      if (req == NULL)
      {
        break;
      }
  
 -    for (i = 0; (uint32_t) i < oid_list_len; i++)
 -      snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len);
 +    oid_list_todo_num = 0;
 +    for (j = 0; j < oid_list_len; j++)
 +    {
 +      /* Do not rerequest already finished OIDs */
 +      if (!oid_list_todo[j])
 +        continue;
 +      oid_list_todo_num++;
 +      snmp_add_null_var (req, oid_list[j].oid, oid_list[j].oid_len);
 +    }
 +
 +    if (oid_list_todo_num == 0)
 +    {
 +      /* The request is still empty - so we are finished */
 +      DEBUG ("snmp plugin: all variables have left their subtree");
 +      status = 0;
 +      break;
 +    }
  
      res = NULL;
      status = snmp_sess_synch_response (host->sess_handle, req, &res);
 -
      if ((status != STAT_SUCCESS) || (res == NULL))
      {
        char *errstr = NULL;
        status = -1;
        break;
      }
 +
      status = 0;
      assert (res != NULL);
      c_release (LOG_INFO, &host->complaint,
        break;
      }
  
 -    /* Check if all values (and possibly the instance) have left their
 -     * subtree */
 -    if (csnmp_check_res_left_subtree (host, data, res) != 0)
 +    for (vb = res->variables, i = 0; (vb != NULL); vb = vb->next_variable, i++)
      {
 -      status = 0;
 -      break;
 -    }
 +      /* Calculate value index from todo list */
 +      while (!oid_list_todo[i] && (i < oid_list_len))
 +        i++;
  
 -    /* Copy the OID of the value used as instance to oid_list, if an instance
 -     * is configured. */
 -    if (data->instance.oid.oid_len > 0)
 -    {
 -      /* Allocate a new `csnmp_list_instances_t', insert the instance name and
 -       * add it to the list */
 -      if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail,
 -            res, &data->instance.oid) != 0)
 +      /* An instance is configured and the res variable we process is the
 +       * instance value (last index) */
 +      if ((data->instance.oid.oid_len > 0) && (i == data->values_len))
        {
 -        ERROR ("snmp plugin: csnmp_instance_list_add failed.");
 -        status = -1;
 -        break;
 -      }
 -
 -      /* The instance OID is added to the list of OIDs to GET from the
 -       * snmp agent last, so set vb on the last variable returned and copy
 -       * that OID. */
 -      for (vb = res->variables;
 -          (vb != NULL) && (vb->next_variable != NULL);
 -          vb = vb->next_variable)
 -        /* do nothing */;
 -      assert (vb != NULL);
 -
 -      /* Copy the OID of the instance value to oid_list[data->values_len].
 -       * "oid_list" is used for the next GETNEXT request. */
 -      memcpy (oid_list[data->values_len].oid, vb->name,
 -          sizeof (oid) * vb->name_length);
 -      oid_list[data->values_len].oid_len = vb->name_length;
 -    }
 -
 -    /* Iterate over all the (non-instance) values returned by the agent. The
 -     * (i < value_len) check will make sure we're not handling the instance OID
 -     * twice. */
 -    for (vb = res->variables, i = 0;
 -        (vb != NULL) && (i < data->values_len);
 -        vb = vb->next_variable, i++)
 -    {
 -      csnmp_table_values_t *vt;
 -      oid_t vb_name;
 -      oid_t suffix;
 -
 -      csnmp_oid_init (&vb_name, vb->name, vb->name_length);
 -
 -      /* Calculate the current suffix. This is later used to check that the
 -       * suffix is increasing. This also checks if we left the subtree */
 -      status = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
 -      if (status != 0)
 -      {
 -        DEBUG ("snmp plugin: host = %s; data = %s; Value %i failed. "
 -            "It probably left its subtree.",
 -            host->name, data->name, i);
 -        continue;
 -      }
 -
 -      /* Make sure the OIDs returned by the agent are increasing. Otherwise our
 -       * table matching algorithm will get confused. */
 -      if ((value_list_tail[i] != NULL)
 -          && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0))
 -      {
 -        DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
 -            "Suffix is not increasing.",
 -            host->name, data->name, i);
 -        continue;
 +        if ((vb->type == SNMP_ENDOFMIBVIEW)
 +            || (snmp_oid_ncompare (data->instance.oid.oid,
 +                data->instance.oid.oid_len,
 +                vb->name, vb->name_length,
 +                data->instance.oid.oid_len) != 0))
 +        {
 +          DEBUG ("snmp plugin: host = %s; data = %s; Instance left its subtree.",
 +              host->name, data->name);
 +          oid_list_todo[i] = 0;
 +          continue;
 +        }
 +
 +        /* Allocate a new `csnmp_list_instances_t', insert the instance name and
 +         * add it to the list */
 +        if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail,
 +              res, host, data) != 0)
 +        {
 +          ERROR ("snmp plugin: csnmp_instance_list_add failed.");
 +          status = -1;
 +          break;
 +        }
        }
 -
 -      vt = malloc (sizeof (*vt));
 -      if (vt == NULL)
 +      else /* The variable we are processing is a normal value */
        {
 -        ERROR ("snmp plugin: malloc failed.");
 -        status = -1;
 -        break;
 +        csnmp_table_values_t *vt;
 +        oid_t vb_name;
 +        oid_t suffix;
 +        int ret;
 +
 +        csnmp_oid_init (&vb_name, vb->name, vb->name_length);
 +
 +        /* Calculate the current suffix. This is later used to check that the
 +         * suffix is increasing. This also checks if we left the subtree */
 +        ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
 +        if (ret != 0)
 +        {
 +          DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
 +              "Value probably left its subtree.",
 +              host->name, data->name, i);
 +          oid_list_todo[i] = 0;
 +          continue;
 +        }
 +
 +        /* Make sure the OIDs returned by the agent are increasing. Otherwise our
 +         * table matching algorithm will get confused. */
 +        if ((value_list_tail[i] != NULL)
 +            && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0))
 +        {
 +          DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
 +              "Suffix is not increasing.",
 +              host->name, data->name, i);
 +          oid_list_todo[i] = 0;
 +          continue;
 +        }
 +
 +        vt = malloc (sizeof (*vt));
 +        if (vt == NULL)
 +        {
 +          ERROR ("snmp plugin: malloc failed.");
 +          status = -1;
 +          break;
 +        }
 +        memset (vt, 0, sizeof (*vt));
 +
 +        vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type,
 +            data->scale, data->shift, host->name, data->name);
 +        memcpy (&vt->suffix, &suffix, sizeof (vt->suffix));
 +        vt->next = NULL;
 +
 +        if (value_list_tail[i] == NULL)
 +          value_list_head[i] = vt;
 +        else
 +          value_list_tail[i]->next = vt;
 +        value_list_tail[i] = vt;
        }
 -      memset (vt, 0, sizeof (*vt));
 -
 -      vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type,
 -          data->scale, data->shift);
 -      memcpy (&vt->suffix, &suffix, sizeof (vt->suffix));
 -      vt->next = NULL;
  
 -      if (value_list_tail[i] == NULL)
 -        value_list_head[i] = vt;
 -      else
 -        value_list_tail[i]->next = vt;
 -      value_list_tail[i] = vt;
 -
 -      /* Copy OID to oid_list[i + 1] */
 +      /* Copy OID to oid_list[i] */
        memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length);
        oid_list[i].oid_len = vb->name_length;
 -    } /* for (i = data->values_len) */
 +
 +    } /* for (vb = res->variables ...) */
  
      if (res != NULL)
        snmp_free_pdu (res);
      snmp_free_pdu (res);
    res = NULL;
  
+   if (req != NULL)
+     snmp_free_pdu (req);
+   req = NULL;
    if (status == 0)
      csnmp_dispatch_table (host, data, instance_list_head, value_list_head);
  
  
    sfree (value_list_head);
    sfree (value_list_tail);
 -  sfree (oid_list);
  
    return (0);
  } /* int csnmp_read_table */
@@@ -1564,7 -1635,7 +1568,7 @@@ static int csnmp_read_value (host_defin
        if (snmp_oid_compare (data->values[i].oid, data->values[i].oid_len,
              vb->name, vb->name_length) == 0)
          vl.values[i] = csnmp_value_list_to_value (vb, ds->ds[i].type,
 -            data->scale, data->shift);
 +            data->scale, data->shift, host->name, data->name);
    } /* for (res->variables) */
  
    if (res != NULL)
  static int csnmp_read_host (user_data_t *ud)
  {
    host_definition_t *host;
 -  time_t time_start;
 -  time_t time_end;
 +  cdtime_t time_start;
 +  cdtime_t time_end;
    int status;
    int success;
    int i;
    host = ud->data;
  
    if (host->interval == 0)
 -    host->interval = interval_g;
 +    host->interval = plugin_get_interval ();
  
 -  time_start = time (NULL);
 -  DEBUG ("snmp plugin: csnmp_read_host (%s) started at %u;", host->name,
 -      (unsigned int) time_start);
 +  time_start = cdtime ();
  
    if (host->sess_handle == NULL)
      csnmp_host_open_session (host);
        success++;
    }
  
 -  time_end = time (NULL);
 -  DEBUG ("snmp plugin: csnmp_read_host (%s) finished at %u;", host->name,
 -      (unsigned int) time_end);
 -  if ((uint32_t) (time_end - time_start) > host->interval)
 +  time_end = cdtime ();
 +  if ((time_end - time_start) > host->interval)
    {
 -    WARNING ("snmp plugin: Host `%s' should be queried every %"PRIu32
 -        " seconds, but reading all values takes %u seconds.",
 -        host->name, host->interval, (unsigned int) (time_end - time_start));
 +    WARNING ("snmp plugin: Host `%s' should be queried every %.3f "
 +        "seconds, but reading all values takes %.3f seconds.",
 +        host->name,
 +        CDTIME_T_TO_DOUBLE (host->interval),
 +        CDTIME_T_TO_DOUBLE (time_end - time_start));
    }
  
    if (success == 0)
diff --combined src/write_http.c
@@@ -61,7 -61,7 +61,7 @@@ struct wh_callback_
          char   send_buffer[4096];
          size_t send_buffer_free;
          size_t send_buffer_fill;
 -        time_t send_buffer_init_time;
 +        cdtime_t send_buffer_init_time;
  
          pthread_mutex_t send_lock;
  };
@@@ -72,7 -72,7 +72,7 @@@ static void wh_reset_buffer (wh_callbac
          memset (cb->send_buffer, 0, sizeof (cb->send_buffer));
          cb->send_buffer_free = sizeof (cb->send_buffer);
          cb->send_buffer_fill = 0;
 -        cb->send_buffer_init_time = time (NULL);
 +        cb->send_buffer_init_time = cdtime ();
  
          if (cb->format == WH_FORMAT_JSON)
          {
@@@ -158,21 -158,19 +158,21 @@@ static int wh_callback_init (wh_callbac
          return (0);
  } /* }}} int wh_callback_init */
  
 -static int wh_flush_nolock (int timeout, wh_callback_t *cb) /* {{{ */
 +static int wh_flush_nolock (cdtime_t timeout, wh_callback_t *cb) /* {{{ */
  {
          int status;
  
 -        DEBUG ("write_http plugin: wh_flush_nolock: timeout = %i; "
 +        DEBUG ("write_http plugin: wh_flush_nolock: timeout = %.3f; "
                          "send_buffer_fill = %zu;",
 -                        timeout, cb->send_buffer_fill);
 +                        CDTIME_T_TO_DOUBLE (timeout),
 +                        cb->send_buffer_fill);
  
 +        /* timeout == 0  => flush unconditionally */
          if (timeout > 0)
          {
 -                time_t now;
 +                cdtime_t now;
  
 -                now = time (NULL);
 +                now = cdtime ();
                  if ((cb->send_buffer_init_time + timeout) > now)
                          return (0);
          }
          {
                  if (cb->send_buffer_fill <= 0)
                  {
 -                        cb->send_buffer_init_time = time (NULL);
 +                        cb->send_buffer_init_time = cdtime ();
                          return (0);
                  }
  
          {
                  if (cb->send_buffer_fill <= 2)
                  {
 -                        cb->send_buffer_init_time = time (NULL);
 +                        cb->send_buffer_init_time = cdtime ();
                          return (0);
                  }
  
          return (status);
  } /* }}} wh_flush_nolock */
  
 -static int wh_flush (int timeout, /* {{{ */
 +static int wh_flush (cdtime_t timeout, /* {{{ */
                  const char *identifier __attribute__((unused)),
                  user_data_t *user_data)
  {
@@@ -261,7 -259,7 +261,7 @@@ static void wh_callback_free (void *dat
  
          cb = data;
  
 -        wh_flush_nolock (/* timeout = */ -1, cb);
 +        wh_flush_nolock (/* timeout = */ 0, cb);
  
          curl_easy_cleanup (cb->curl);
          sfree (cb->location);
          sfree (cb);
  } /* }}} void wh_callback_free */
  
 -static int wh_value_list_to_string (char *buffer, /* {{{ */
 -                size_t buffer_size,
 -                const data_set_t *ds, const value_list_t *vl,
 -                wh_callback_t *cb)
 -{
 -        size_t offset = 0;
 -        int status;
 -        int i;
 -        gauge_t *rates = NULL;
 -
 -        assert (0 == strcmp (ds->type, vl->type));
 -
 -        memset (buffer, 0, buffer_size);
 -
 -#define BUFFER_ADD(...) do { \
 -        status = ssnprintf (buffer + offset, buffer_size - offset, \
 -                        __VA_ARGS__); \
 -        if (status < 1) \
 -        { \
 -                sfree (rates); \
 -                return (-1); \
 -        } \
 -        else if (((size_t) status) >= (buffer_size - offset)) \
 -        { \
 -                sfree (rates); \
 -                return (-1); \
 -        } \
 -        else \
 -                offset += ((size_t) status); \
 -} while (0)
 -
 -        BUFFER_ADD ("%lu", (unsigned long) vl->time);
 -
 -        for (i = 0; i < ds->ds_num; i++)
 -        {
 -                if (ds->ds[i].type == DS_TYPE_GAUGE)
 -                        BUFFER_ADD (":%f", vl->values[i].gauge);
 -                else if (cb->store_rates)
 -                {
 -                        if (rates == NULL)
 -                                rates = uc_get_rate (ds, vl);
 -                        if (rates == NULL)
 -                        {
 -                                WARNING ("write_http plugin: "
 -                                                "uc_get_rate failed.");
 -                                return (-1);
 -                        }
 -                        BUFFER_ADD (":%g", rates[i]);
 -                }
 -                else if (ds->ds[i].type == DS_TYPE_COUNTER)
 -                        BUFFER_ADD (":%llu", vl->values[i].counter);
 -                else if (ds->ds[i].type == DS_TYPE_DERIVE)
 -                        BUFFER_ADD (":%"PRIi64, vl->values[i].derive);
 -                else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
 -                        BUFFER_ADD (":%"PRIu64, vl->values[i].absolute);
 -                else
 -                {
 -                        ERROR ("write_http plugin: Unknown data source type: %i",
 -                                        ds->ds[i].type);
 -                        sfree (rates);
 -                        return (-1);
 -                }
 -        } /* for ds->ds_num */
 -
 -#undef BUFFER_ADD
 -
 -        sfree (rates);
 -        return (0);
 -} /* }}} int wh_value_list_to_string */
 -
  static int wh_write_command (const data_set_t *ds, const value_list_t *vl, /* {{{ */
                  wh_callback_t *cb)
  {
  
          /* Convert the values to an ASCII representation and put that into
           * `values'. */
 -        status = wh_value_list_to_string (values, sizeof (values), ds, vl, cb);
 +        status = format_values (values, sizeof (values), ds, vl, cb->store_rates);
          if (status != 0) {
                  ERROR ("write_http plugin: error with "
                                  "wh_value_list_to_string");
          }
  
          command_len = (size_t) ssnprintf (command, sizeof (command),
 -                        "PUTVAL %s interval=%i %s\r\n",
 -                        key, vl->interval, values);
 +                        "PUTVAL %s interval=%.3f %s\r\n",
 +                        key,
 +                        CDTIME_T_TO_DOUBLE (vl->interval),
 +                        values);
          if (command_len >= sizeof (command)) {
                  ERROR ("write_http plugin: Command buffer too small: "
                                  "Need %zu bytes.", command_len + 1);
  
          if (command_len >= cb->send_buffer_free)
          {
 -                status = wh_flush_nolock (/* timeout = */ -1, cb);
 +                status = wh_flush_nolock (/* timeout = */ 0, cb);
                  if (status != 0)
                  {
                          pthread_mutex_unlock (&cb->send_lock);
@@@ -384,7 -450,7 +384,7 @@@ static int wh_write_json (const data_se
                          ds, vl, cb->store_rates);
          if (status == (-ENOMEM))
          {
 -                status = wh_flush_nolock (/* timeout = */ -1, cb);
 +                status = wh_flush_nolock (/* timeout = */ 0, cb);
                  if (status != 0)
                  {
                          wh_reset_buffer (cb);
@@@ -590,9 -656,18 +590,18 @@@ static int wh_config (oconfig_item_t *c
          return (0);
  } /* }}} int wh_config */
  
+ static int wh_init (void) /* {{{ */
+ {
+         /* Call this while collectd is still single-threaded to avoid
+          * initialization issues in libgcrypt. */
+         curl_global_init (CURL_GLOBAL_SSL);
+         return (0);
+ } /* }}} int wh_init */
  void module_register (void) /* {{{ */
  {
          plugin_register_complex_config ("write_http", wh_config);
+         plugin_register_init ("write_http", wh_init);
  } /* }}} void module_register */
  
  /* vim: set fdm=marker sw=8 ts=8 tw=78 et : */