Merge branch 'collectd-5.6' into collectd-5.7
authorRuben Kerkhof <ruben@rubenkerkhof.com>
Fri, 24 Feb 2017 16:44:55 +0000 (17:44 +0100)
committerRuben Kerkhof <ruben@rubenkerkhof.com>
Fri, 24 Feb 2017 16:44:55 +0000 (17:44 +0100)
1  2 
configure.ac
src/daemon/common.c
src/daemon/common.h

diff --combined configure.ac
@@@ -214,54 -214,7 +214,54 @@@ 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 fnmatch.h libgen.h)
 +AC_CHECK_HEADERS([ \
 +  arpa/inet.h \
 +  assert.h \
 +  ctype.h \
 +  endian.h \
 +  errno.h \
 +  fcntl.h \
 +  fnmatch.h \
 +  fs_info.h \
 +  fshelp.h \
 +  grp.h \
 +  kstat.h \
 +  kvm.h \
 +  libgen.h \
 +  limits.h \
 +  locale.h \
 +  math.h \
 +  mntent.h \
 +  mnttab.h \
 +  netdb.h \
 +  paths.h \
 +  poll.h \
 +  pthread_np.h \
 +  pwd.h \
 +  regex.h \
 +  signal.h \
 +  stdarg.h \
 +  stdio.h \
 +  sys/fs_types.h \
 +  sys/fstyp.h \
 +  sys/ioctl.h \
 +  sys/isa_defs.h \
 +  sys/mntent.h \
 +  sys/mnttab.h \
 +  sys/param.h \
 +  sys/resource.h \
 +  sys/select.h \
 +  sys/socket.h \
 +  sys/statfs.h \
 +  sys/statvfs.h \
 +  sys/types.h \
 +  sys/un.h \
 +  sys/vfs.h \
 +  sys/vfstab.h \
 +  sys/vmmeter.h \
 +  syslog.h \
 +  wordexp.h \
 +])
  
  # For entropy plugin on newer NetBSD
  AC_CHECK_HEADERS(sys/rndio.h, [], [],
@@@ -705,6 -658,31 +705,6 @@@ AC_CHECK_HEADERS(linux/un.h, [], []
  #endif
  ])
  
 -AC_CHECK_HEADERS([ \
 -  ctype.h \
 -  fs_info.h \
 -  fshelp.h \
 -  grp.h \
 -  kvm.h \
 -  limits.h \
 -  locale.h \
 -  mntent.h \
 -  mnttab.h \
 -  paths.h \
 -  pwd.h \
 -  sys/fs_types.h \
 -  sys/fstyp.h \
 -  sys/mntent.h \
 -  sys/mnttab.h \
 -  sys/statfs.h \
 -  sys/statvfs.h \
 -  sys/un.h \
 -  sys/vfs.h \
 -  sys/vfstab.h \
 -  sys/vmmeter.h \
 -  wordexp.h \
 -])
 -
  # --enable-xfs {{{
  AC_ARG_ENABLE([xfs],
    [AS_HELP_STRING([--enable-xfs], [xfs support in df plugin @<:@default=yes@:>@])],
@@@ -835,12 -813,12 +835,12 @@@ AC_CHECK_HEADERS(sys/capability.h
                   [have_capability="yes"],
                   [have_capability="no (<sys/capability.h> not found)"])
  if test "x$have_capability" = "xyes"; then
- AC_CHECK_LIB(cap, cap_get_bound,
+ AC_CHECK_LIB(cap, cap_get_proc,
                   [have_capability="yes"],
-                  [have_capability="no (cap_get_bound() not found)"])
+                  [have_capability="no (cap_get_proc() not found)"])
  fi
  if test "x$have_capability" = "xyes"; then
-   AC_DEFINE(HAVE_CAPABILITY, 1, [Define to 1 if you have cap_get_bound() (-lcap).])
+   AC_DEFINE(HAVE_CAPABILITY, 1, [Define to 1 if you have cap_get_proc() (-lcap).])
  fi
  AM_CONDITIONAL(BUILD_WITH_CAPABILITY, test "x$have_capability" = "xyes")
  
@@@ -1684,45 -1662,6 +1684,45 @@@ AC_CHECK_MEMBERS([kstat_io_t.nwritten, 
  #endif
        ])
  
 +# check for pthread_setname_np
 +SAVE_LDFLAGS="$LDFLAGS"
 +LDFLAGS="$LDFLAGS -lpthread"
 +
 +AC_MSG_CHECKING([for pthread_setname_np])
 +      have_pthread_setname_np="no"
 +      AC_LINK_IFELSE([AC_LANG_PROGRAM(
 +[[
 +#define _GNU_SOURCE
 +#include <pthread.h>
 +]],
 +[[
 +        pthread_setname_np((pthread_t) {0}, "conftest");
 +]]
 +      )], [
 +              have_pthread_setname_np="yes"
 +              AC_DEFINE(HAVE_PTHREAD_SETNAME_NP, 1, [pthread_setname_np() is available.])
 +      ])
 +
 +AC_MSG_RESULT([$have_pthread_setname_np])
 +
 +# check for pthread_set_name_np(3) (FreeBSD)
 +AC_MSG_CHECKING([for pthread_set_name_np])
 +      have_pthread_set_name_np="no"
 +      AC_LINK_IFELSE([AC_LANG_PROGRAM(
 +[[
 +#include <pthread_np.h>
 +]],
 +[[
 +        pthread_set_name_np((pthread_t) {0}, "conftest");
 +]]
 +      )], [
 +              have_pthread_set_name_np="yes"
 +              AC_DEFINE(HAVE_PTHREAD_SET_NAME_NP, 1, [pthread_set_name_np() is available.])
 +      ])
 +AC_MSG_RESULT([$have_pthread_set_name_np])
 +
 +LDFLAGS="$SAVE_LDFLAGS"
 +
  #
  # Checks for libraries begin here
  #
  fi
  # }}}
  
 +# --with-libdpdk {{{
 +AC_ARG_VAR([LIBDPDK_CPPFLAGS], [Preprocessor flags for libdpdk])
 +AC_ARG_VAR([LIBDPDK_LDFLAGS], [Linker flags for libdpdk])
 +
 +AC_ARG_WITH([libdpdk], [AS_HELP_STRING([--without-libdpdk], [Disable libdpdk.])])
 +
 +if test "x$with_libdpdk" != "xno"
 +then
 +      if test "x$LIBDPDK_CPPFLAGS" = "x"
 +      then
 +              LIBDPDK_CPPFLAGS="-I/usr/include/dpdk"
 +      fi
 +      SAVE_CPPFLAGS="$CPPFLAGS"
 +      CPPFLAGS="$LIBDPDK_CPPFLAGS $CPPFLAGS"
 +      AC_CHECK_HEADERS([rte_config.h],
 +              [with_libdpdk="yes"],
 +              [with_libdpdk="no (rte_config.h not found)"]
 +      )
 +      CPPFLAGS="$SAVE_CPPFLAGS"
 +fi
 +
 +if test "x$with_libdpdk" = "xyes"
 +then
 +      SAVE_LDFLAGS="$LDFLAGS"
 +      LDFLAGS="$LIBDPDK_LDFLAGS $LDFLAGS"
 +      AC_CHECK_LIB([dpdk], [rte_eal_init],
 +              [with_libdpdk="yes"],
 +              [with_libdpdk="no (symbol 'rte_eal_init' not found)"]
 +      )
 +      LDFLAGS="$SAVE_LDFLAGS"
 +fi
 +
 +# }}}
 +
  # --with-java {{{
  with_java_home="$JAVA_HOME"
  if test "x$with_java_home" = "x"
  AM_CONDITIONAL(BUILD_WITH_LIBMEMCACHED, test "x$with_libmemcached" = "xyes")
  # }}}
  
 +# --with-libmicrohttpd {{{
 +with_libmicrohttpd_cppflags=""
 +with_libmicrohttpd_ldflags=""
 +AC_ARG_WITH([libmicrohttpd], [AS_HELP_STRING([--with-libmicrohttpd@<:@=PREFIX@:>@], [Path to libmicrohttpd.])],
 +  [
 +    if test "x$withval" != "xno" && test "x$withval" != "xyes"
 +    then
 +      with_libmicrohttpd_cppflags="-I$withval/include"
 +      with_libmicrohttpd_ldflags="-L$withval/lib"
 +      with_libmicrohttpd="yes"
 +    fi
 +    if test "x$withval" = "xno"
 +    then
 +      with_libmicrohttpd="no (disabled on command line)"
 +    fi
 +  ],
 +  [withval="yes"]
 +)
 +if test "x$withval" = "xyes"
 +then
 +PKG_CHECK_MODULES([MICROHTTPD], [libmicrohttpd],
 +  [with_libmicrohttpd="yes"],
 +  [with_libmicrohttpd="no (pkg-config could not find libmicrohttpd)"]
 +)
 +fi
 +
 +if test "x$MICROHTTPD_LIBS" = "x"
 +then
 +  MICROHTTPD_LIBS="-lmicrohttpd"
 +fi
 +
 +SAVE_CPPFLAGS="$CPPFLAGS"
 +SAVE_LDFLAGS="$LDFLAGS"
 +SAVE_LIBS="$LIBS"
 +CPPFLAGS="$with_libmicrohttpd_cppflags $MICROHTTPD_CFLAGS"
 +LDFLAGS="$with_libmicrohttpd_ldflags $LDFLAGS"
 +LIBS="$LIBS $MICROHTTPD_LIBS"
 +
 +if test "x$with_libmicrohttpd" = "xyes"
 +then
 +  AC_CHECK_HEADERS([microhttpd.h],
 +                   [with_libmicrohttpd="yes"],
 +                   [with_libmicrohttpd="no (<microhttpd.h> not found)"])
 +fi
 +
 +if test "x$with_libmicrohttpd" = "xyes"
 +then
 +  AC_CHECK_LIB([microhttpd], [MHD_start_daemon],
 +               [with_libmicrohttpd="yes"],
 +               [with_libmicrohttpd="no (libmicrohttpd not found)"])
 +fi
 +
 +CPPFLAGS="$SAVE_CPPFLAGS"
 +LDFLAGS="$SAVE_LDFLAGS"
 +LIBS="$SAVE_LIBS"
 +
 +BUILD_WITH_LIBMICROHTTPD_CPPFLAGS="$with_libmicrohttpd_cppflags $MICROHTTPD_CFLAGS"
 +BUILD_WITH_LIBMICROHTTPD_LDFLAGS="$with_libmicrohttpd_ldflags"
 +BUILD_WITH_LIBMICROHTTPD_LIBS="$MICROHTTPD_LIBS"
 +AC_SUBST([BUILD_WITH_LIBMICROHTTPD_CPPFLAGS])
 +AC_SUBST([BUILD_WITH_LIBMICROHTTPD_LDFLAGS])
 +AC_SUBST([BUILD_WITH_LIBMICROHTTPD_LIBS])
 +# }}}
 +
  # --with-libmodbus {{{
  with_libmodbus_config=""
  with_libmodbus_cflags=""
  AM_CONDITIONAL(BUILD_WITH_LIBPQ, test "x$with_libpq" = "xyes")
  # }}}
  
 +# --with-libpqos {{{
 +with_libpqos_cppflags=""
 +with_libpqos_ldflags=""
 +AC_ARG_WITH(libpqos, [AS_HELP_STRING([--with-libpqos@<:@=PREFIX@:>@], [Path to libpqos.])],
 +[
 +      if test "x$withval" != "xno" && test "x$withval" != "xyes"
 +      then
 +              with_libpqos_cppflags="-I$withval/include"
 +              with_libpqos_ldflags="-L$withval/lib"
 +              with_libpqos="yes"
 +      else
 +              with_libpqos="$withval"
 +      fi
 +],
 +[
 +      with_libpqos="yes"
 +])
 +if test "x$with_libpqos" = "xyes"
 +then
 +      SAVE_CPPFLAGS="$CPPFLAGS"
 +      CPPFLAGS="$CPPFLAGS $with_libpqos_cppflags"
 +
 +      AC_CHECK_HEADERS(pqos.h, [with_libpqos="yes"], [with_libpqos="no (pqos.h not found)"])
 +
 +      CPPFLAGS="$SAVE_CPPFLAGS"
 +fi
 +if test "x$with_libpqos" = "xyes"
 +then
 +      SAVE_CPPFLAGS="$CPPFLAGS"
 +      SAVE_LDFLAGS="$LDFLAGS"
 +      CPPFLAGS="$CPPFLAGS $with_libpqos_cppflags"
 +      LDFLAGS="$LDFLAGS $with_libpqos_ldflags"
 +
 +      AC_CHECK_LIB(pqos, pqos_init, [with_libpqos="yes"], [with_libpqos="no (Can't find libpqos)"])
 +
 +      CPPFLAGS="$SAVE_CPPFLAGS"
 +      LDFLAGS="$SAVE_LDFLAGS"
 +fi
 +if test "x$with_libpqos" = "xyes"
 +then
 +  SAVE_CPPFLAGS="$CPPFLAGS"
 +  CPPFLAGS="$CPPFLAGS $with_libpqos_cppflags"
 +  AC_RUN_IFELSE([AC_LANG_PROGRAM(
 +    [[#include <pqos.h>]],
 +    [[return !(PQOS_VERSION >= 106)]])],
 +    [with_libpqos="yes"], [with_libpqos="no (pqos library version 1.06 or higher is required)"])
 +  CPPFLAGS="$SAVE_CPPFLAGS"
 +fi
 +if test "x$with_libpqos" = "xyes"
 +then
 +      BUILD_WITH_LIBPQOS_CPPFLAGS="$with_libpqos_cppflags"
 +      BUILD_WITH_LIBPQOS_LDFLAGS="$with_libpqos_ldflags"
 +      BUILD_WITH_LIBPQOS_LIBS="-lpqos"
 +      AC_SUBST(BUILD_WITH_LIBPQOS_CPPFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBPQOS_LDFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBPQOS_LIBS)
 +fi
 +# }}}
 +
  # --with-libprotobuf {{{
  with_libprotobuf_cppflags=""
  with_libprotobuf_ldflags=""
@@@ -5933,15 -5715,12 +5933,15 @@@ plugin_curl_xml="no
  plugin_df="no"
  plugin_disk="no"
  plugin_drbd="no"
 +plugin_dpdkstat="no"
  plugin_entropy="no"
  plugin_ethstat="no"
  plugin_fhcount="no"
  plugin_fscache="no"
  plugin_gps="no"
  plugin_grpc="no"
 +plugin_hugepages="no"
 +plugin_intel_rdt="no"
  plugin_interface="no"
  plugin_ipmi="no"
  plugin_ipvs="no"
@@@ -5971,7 -5750,6 +5971,7 @@@ plugin_virt="no
  plugin_vmem="no"
  plugin_vserver="no"
  plugin_wireless="no"
 +plugin_write_prometheus="no"
  plugin_xencpu="no"
  plugin_zfs_arc="no"
  plugin_zone="no"
@@@ -5991,7 -5769,6 +5991,7 @@@ the
        plugin_entropy="yes"
        plugin_fhcount="yes"
        plugin_fscache="yes"
 +      plugin_hugepages="yes"
        plugin_interface="yes"
        plugin_ipc="yes"
        plugin_irq="yes"
  if test "x$have_protoc_c" = "xyes" && test "x$with_libprotobuf_c" = "xyes"
  then
        plugin_pinba="yes"
 +      if test "x$with_libmicrohttpd" = "xyes"
 +      then
 +              plugin_write_prometheus="yes"
 +      fi
  fi
  
  # Mac OS X memory interface
    plugin_xencpu="yes"
  fi
  
 +if test "x$with_libdpdk" = "xyes"
 +then
 +  plugin_dpdkstat="yes"
 +fi
 +
  m4_divert_once([HELP_ENABLE], [
  collectd plugins:])
  
@@@ -6395,7 -6163,6 +6395,7 @@@ AC_PLUGIN([dbi],                 [$with
  AC_PLUGIN([df],                  [$plugin_df],              [Filesystem usage statistics])
  AC_PLUGIN([disk],                [$plugin_disk],            [Disk usage statistics])
  AC_PLUGIN([dns],                 [$with_libpcap],           [DNS traffic analysis])
 +AC_PLUGIN([dpdkstat],            [$plugin_dpdkstat],        [Stats & Status from DPDK])
  AC_PLUGIN([drbd],                [$plugin_drbd],            [DRBD statistics])
  AC_PLUGIN([email],               [yes],                     [EMail statistics])
  AC_PLUGIN([entropy],             [$plugin_entropy],         [Entropy statistics])
@@@ -6408,8 -6175,6 +6408,8 @@@ AC_PLUGIN([gmond],               [$with
  AC_PLUGIN([gps],                 [$plugin_gps],             [GPS plugin])
  AC_PLUGIN([grpc],                [$plugin_grpc],            [gRPC plugin])
  AC_PLUGIN([hddtemp],             [yes],                     [Query hddtempd])
 +AC_PLUGIN([hugepages],           [$plugin_hugepages],       [Hugepages statistics])
 +AC_PLUGIN([intel_rdt],           [$with_libpqos],           [Intel RDT monitor plugin])
  AC_PLUGIN([interface],           [$plugin_interface],       [Interface traffic statistics])
  AC_PLUGIN([ipc],                 [$plugin_ipc],             [IPC statistics])
  AC_PLUGIN([ipmi],                [$plugin_ipmi],            [IPMI sensor statistics])
@@@ -6507,7 -6272,6 +6507,7 @@@ AC_PLUGIN([write_http],          [$with
  AC_PLUGIN([write_kafka],         [$with_librdkafka],        [Kafka output plugin])
  AC_PLUGIN([write_log],           [yes],                     [Log output plugin])
  AC_PLUGIN([write_mongodb],       [$with_libmongoc],         [MongoDB output plugin])
 +AC_PLUGIN([write_prometheus],    [$plugin_write_prometheus], [Prometheus write plugin])
  AC_PLUGIN([write_redis],         [$with_libhiredis],        [Redis output plugin])
  AC_PLUGIN([write_riemann],       [$with_libriemann_client], [Riemann output plugin])
  AC_PLUGIN([write_sensu],         [yes],                     [Sensu output plugin])
@@@ -6738,7 -6502,6 +6738,7 @@@ AC_MSG_RESULT([    libaquaero5 . . . . 
  AC_MSG_RESULT([    libatasmart . . . . . $with_libatasmart])
  AC_MSG_RESULT([    libcurl . . . . . . . $with_libcurl])
  AC_MSG_RESULT([    libdbi  . . . . . . . $with_libdbi])
 +AC_MSG_RESULT([    libdpdk . . . . . . . $with_libdpdk])
  AC_MSG_RESULT([    libesmtp  . . . . . . $with_libesmtp])
  AC_MSG_RESULT([    libganglia  . . . . . $with_libganglia])
  AC_MSG_RESULT([    libgcrypt . . . . . . $with_libgcrypt])
@@@ -6756,7 -6519,6 +6756,7 @@@ AC_MSG_RESULT([    libldap . . . . . . 
  AC_MSG_RESULT([    liblua  . . . . . . . $with_liblua])
  AC_MSG_RESULT([    liblvm2app  . . . . . $with_liblvm2app])
  AC_MSG_RESULT([    libmemcached  . . . . $with_libmemcached])
 +AC_MSG_RESULT([    libmicrohttpd . . . . $with_libmicrohttpd])
  AC_MSG_RESULT([    libmnl  . . . . . . . $with_libmnl])
  AC_MSG_RESULT([    libmodbus . . . . . . $with_libmodbus])
  AC_MSG_RESULT([    libmongoc . . . . . . $with_libmongoc])
@@@ -6773,7 -6535,6 +6773,7 @@@ AC_MSG_RESULT([    libpcap . . . . . . 
  AC_MSG_RESULT([    libperfstat . . . . . $with_perfstat])
  AC_MSG_RESULT([    libperl . . . . . . . $with_libperl])
  AC_MSG_RESULT([    libpq . . . . . . . . $with_libpq])
 +AC_MSG_RESULT([    libpqos . . . . . . . $with_libpqos])
  AC_MSG_RESULT([    libprotobuf . . . . . $with_libprotobuf])
  AC_MSG_RESULT([    libprotobuf-c . . . . $with_libprotobuf_c])
  AC_MSG_RESULT([    libpython . . . . . . $with_libpython])
@@@ -6832,7 -6593,6 +6832,7 @@@ AC_MSG_RESULT([    dbi . . . . . . . . 
  AC_MSG_RESULT([    df  . . . . . . . . . $enable_df])
  AC_MSG_RESULT([    disk  . . . . . . . . $enable_disk])
  AC_MSG_RESULT([    dns . . . . . . . . . $enable_dns])
 +AC_MSG_RESULT([    dpdkstat  . . . . . . $enable_dpdkstat])
  AC_MSG_RESULT([    drbd  . . . . . . . . $enable_drbd])
  AC_MSG_RESULT([    email . . . . . . . . $enable_email])
  AC_MSG_RESULT([    entropy . . . . . . . $enable_entropy])
@@@ -6845,8 -6605,6 +6845,8 @@@ AC_MSG_RESULT([    gmond . . . . . . . 
  AC_MSG_RESULT([    gps . . . . . . . . . $enable_gps])
  AC_MSG_RESULT([    grpc  . . . . . . . . $enable_grpc])
  AC_MSG_RESULT([    hddtemp . . . . . . . $enable_hddtemp])
 +AC_MSG_RESULT([    hugepages . . . . . . $enable_hugepages])
 +AC_MSG_RESULT([    intel_rdt. . . . .  . $enable_intel_rdt])
  AC_MSG_RESULT([    interface . . . . . . $enable_interface])
  AC_MSG_RESULT([    ipc . . . . . . . . . $enable_ipc])
  AC_MSG_RESULT([    ipmi  . . . . . . . . $enable_ipmi])
@@@ -6943,7 -6701,6 +6943,7 @@@ AC_MSG_RESULT([    write_http  . . . . 
  AC_MSG_RESULT([    write_kafka . . . . . $enable_write_kafka])
  AC_MSG_RESULT([    write_log . . . . . . $enable_write_log])
  AC_MSG_RESULT([    write_mongodb . . . . $enable_write_mongodb])
 +AC_MSG_RESULT([    write_prometheus. . . $enable_write_prometheus])
  AC_MSG_RESULT([    write_redis . . . . . $enable_write_redis])
  AC_MSG_RESULT([    write_riemann . . . . $enable_write_riemann])
  AC_MSG_RESULT([    write_sensu . . . . . $enable_write_sensu])
diff --combined src/daemon/common.c
@@@ -271,10 -271,8 +271,10 @@@ ssize_t swrite(int fd, const void *buf
    ptr = (const char *)buf;
    nleft = count;
  
 -  if (fd < 0)
 -    return (-1);
 +  if (fd < 0) {
 +    errno = EINVAL;
 +    return errno;
 +  }
  
    /* checking for closed peer connection */
    pfd.fd = fd;
    if (poll(&pfd, 1, 0) > 0) {
      char buffer[32];
      if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
 -      // if recv returns zero (even though poll() said there is data to be
 -      // read),
 -      // that means the connection has been closed
 -      return -1;
 +      /* if recv returns zero (even though poll() said there is data to be
 +       * read), that means the connection has been closed */
 +      return errno ? errno : -1;
      }
    }
  
        continue;
  
      if (status < 0)
 -      return (status);
 +      return errno ? errno : status;
  
      nleft = nleft - ((size_t)status);
      ptr = ptr + ((size_t)status);
@@@ -326,58 -325,44 +326,58 @@@ int strsplit(char *string, char **field
  
  int strjoin(char *buffer, size_t buffer_size, char **fields, size_t fields_num,
              const char *sep) {
 -  size_t avail;
 -  char *ptr;
 -  size_t sep_len;
 +  size_t avail = 0;
 +  char *ptr = buffer;
 +  size_t sep_len = 0;
  
 -  if ((buffer_size < 1) || (fields_num == 0))
 -    return (-1);
 +  size_t buffer_req = 0;
 +
 +  if (((fields_num != 0) && (fields == NULL)) ||
 +      ((buffer_size != 0) && (buffer == NULL)))
 +    return (-EINVAL);
 +
 +  if (buffer != NULL)
 +    buffer[0] = 0;
  
 -  memset(buffer, 0, buffer_size);
 -  ptr = buffer;
 -  avail = buffer_size - 1;
 +  if (buffer_size != 0)
 +    avail = buffer_size - 1;
  
 -  sep_len = 0;
    if (sep != NULL)
      sep_len = strlen(sep);
  
    for (size_t i = 0; i < fields_num; i++) {
 -    size_t field_len;
 +    size_t field_len = strlen(fields[i]);
  
 -    if ((i > 0) && (sep_len > 0)) {
 -      if (avail < sep_len)
 -        return (-1);
 +    if (i != 0)
 +      buffer_req += sep_len;
 +    buffer_req += field_len;
 +
 +    if ((i != 0) && (sep_len > 0)) {
 +      if (sep_len >= avail) {
 +        /* prevent subsequent iterations from writing to the
 +         * buffer. */
 +        avail = 0;
 +        continue;
 +      }
  
        memcpy(ptr, sep, sep_len);
 +
        ptr += sep_len;
        avail -= sep_len;
      }
  
 -    field_len = strlen(fields[i]);
 -    if (avail < field_len)
 -      return (-1);
 +    if (field_len > avail)
 +      field_len = avail;
  
      memcpy(ptr, fields[i], field_len);
      ptr += field_len;
 +
      avail -= field_len;
 +    if (ptr != NULL)
 +      *ptr = 0;
    }
  
 -  assert(buffer[buffer_size - 1] == 0);
 -  return ((int)strlen(buffer));
 +  return (int)buffer_req;
  }
  
  int escape_string(char *buffer, size_t buffer_size) {
@@@ -931,7 -916,7 +931,7 @@@ int format_values(char *ret, size_t ret
  
  int parse_identifier(char *str, char **ret_host, char **ret_plugin,
                       char **ret_plugin_instance, char **ret_type,
 -                     char **ret_type_instance) {
 +                     char **ret_type_instance, char *default_host) {
    char *hostname = NULL;
    char *plugin = NULL;
    char *plugin_instance = NULL;
    plugin++;
  
    type = strchr(plugin, '/');
 -  if (type == NULL)
 -    return (-1);
 -  *type = '\0';
 -  type++;
 +  if (type == NULL) {
 +    if (default_host == NULL)
 +      return (-1);
 +    /* else: no host specified; use default */
 +    type = plugin;
 +    plugin = hostname;
 +    hostname = default_host;
 +  } else {
 +    *type = '\0';
 +    type++;
 +  }
  
    plugin_instance = strchr(plugin, '-');
    if (plugin_instance != NULL) {
@@@ -997,8 -975,7 +997,8 @@@ int parse_identifier_vl(const char *str
    sstrncpy(str_copy, str, sizeof(str_copy));
  
    status = parse_identifier(str_copy, &host, &plugin, &plugin_instance, &type,
 -                            &type_instance);
 +                            &type_instance,
 +                            /* default_host = */ NULL);
    if (status != 0)
      return (status);
  
@@@ -1125,26 -1102,6 +1125,26 @@@ int parse_values(char *buffer, value_li
    return (0);
  } /* int parse_values */
  
 +int parse_value_file(char const *path, value_t *ret_value, int ds_type) {
 +  FILE *fh;
 +  char buffer[256];
 +
 +  fh = fopen(path, "r");
 +  if (fh == NULL)
 +    return (-1);
 +
 +  if (fgets(buffer, sizeof(buffer), fh) == NULL) {
 +    fclose(fh);
 +    return (-1);
 +  }
 +
 +  fclose(fh);
 +
 +  strstripnewline(buffer);
 +
 +  return parse_value(buffer, ret_value, ds_type);
 +} /* int parse_value_file */
 +
  #if !HAVE_GETPWNAM_R
  int getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen,
                 struct passwd **pwbufp) {
@@@ -1465,16 -1422,18 +1465,16 @@@ void set_sock_opts(int sockfd) /* {{{ *
    int status;
    int socktype;
  
 -  socklen_t socklen = sizeof(socklen_t);
 -  int so_keepalive = 1;
 -
 -  status = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &socktype, &socklen);
 +  status = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &socktype,
 +                      &(socklen_t){sizeof(socktype)});
    if (status != 0) {
      WARNING("set_sock_opts: failed to determine socket type");
      return;
    }
  
    if (socktype == SOCK_STREAM) {
 -    status = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &so_keepalive,
 -                        sizeof(so_keepalive));
 +    status =
 +        setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &(int){1}, sizeof(int));
      if (status != 0)
        WARNING("set_sock_opts: failed to set socket keepalive flag");
  
@@@ -1568,16 -1527,26 +1568,26 @@@ void strarray_free(char **array, size_
  #if HAVE_CAPABILITY
  int check_capability(int arg) /* {{{ */
  {
-   cap_value_t cap = (cap_value_t)arg;
+   cap_value_t cap_value = (cap_value_t)arg;
+   cap_t cap;
+   cap_flag_value_t cap_flag_value;
  
-   if (!CAP_IS_SUPPORTED(cap))
+   if (!CAP_IS_SUPPORTED(cap_value))
      return (-1);
  
-   int have_cap = cap_get_bound(cap);
-   if (have_cap != 1)
+   if (!(cap = cap_get_proc())) {
+     ERROR("check_capability: cap_get_proc failed.");
      return (-1);
+   }
  
-   return (0);
+   if (cap_get_flag(cap, cap_value, CAP_EFFECTIVE, &cap_flag_value) < 0) {
+     ERROR("check_capability: cap_get_flag failed.");
+     cap_free(cap);
+     return (-1);
+   }
+   cap_free(cap);
+   return (cap_flag_value != CAP_SET);
  } /* }}} int check_capability */
  #else
  int check_capability(__attribute__((unused)) int arg) /* {{{ */
diff --combined src/daemon/common.h
@@@ -145,12 -145,10 +145,12 @@@ int strsplit(char *string, char **field
   *   is equivalent to the Perl built-in `join'.
   *
   * PARAMETERS
 - *   `dst'         Buffer where the result is stored.
 + *   `dst'         Buffer where the result is stored. Can be NULL if you need to
 + *                 determine the required buffer size only.
   *   `dst_len'     Length of the destination buffer. No more than this many
   *                 bytes will be written to the memory pointed to by `dst',
 - *                 including the trailing null-byte.
 + *                 including the trailing null-byte. Must be zero if dst is
 + *                 NULL.
   *   `fields'      Array of strings to be joined.
   *   `fields_num'  Number of elements in the `fields' array.
   *   `sep'         String to be inserted between any two elements of `fields'.
   *                 Instead of passing "" (empty string) one can pass NULL.
   *
   * RETURN VALUE
 - *   Returns the number of characters in `dst', NOT including the trailing
 - *   null-byte. If an error occurred (empty array or `dst' too small) a value
 - *   smaller than zero will be returned.
 + *   Returns the number of characters in the resulting string, excluding a
 + *   tailing null byte. If this value is greater than or equal to "dst_len", the
 + *   result in "dst" is truncated (but still null terminated). On error a
 + *   negative value is returned.
   */
  int strjoin(char *dst, size_t dst_len, char **fields, size_t fields_num,
              const char *sep);
@@@ -317,17 -314,11 +317,17 @@@ int format_values(char *ret, size_t ret
  
  int parse_identifier(char *str, char **ret_host, char **ret_plugin,
                       char **ret_plugin_instance, char **ret_type,
 -                     char **ret_type_instance);
 +                     char **ret_type_instance, char *default_host);
  int parse_identifier_vl(const char *str, value_list_t *vl);
  int parse_value(const char *value, value_t *ret_value, int ds_type);
  int parse_values(char *buffer, value_list_t *vl, const data_set_t *ds);
  
 +/* parse_value_file reads "path" and parses its content as an integer or
 + * floating point, depending on "ds_type". On success, the value is stored in
 + * "ret_value" and zero is returned. On failure, a non-zero value is returned.
 + */
 +int parse_value_file(char const *path, value_t *ret_value, int ds_type);
 +
  #if !HAVE_GETPWNAM_R
  int getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen,
                 struct passwd **pwbufp);
@@@ -385,7 -376,7 +385,7 @@@ void strarray_free(char **array, size_
   * argument. Returns zero if it does, less than zero if it doesn't or on error.
   * See capabilities(7) for the list of possible capabilities.
   * */
- int check_capability(int capability);
+ int check_capability(int arg);
  #endif /* HAVE_SYS_CAPABILITY_H */
  
  #endif /* COMMON_H */