Merge pull request #3339 from jkohen/patch-1 master
authorMatthias Runge <mrunge@redhat.com>
Thu, 6 Feb 2020 09:59:27 +0000 (10:59 +0100)
committerGitHub <noreply@github.com>
Thu, 6 Feb 2020 09:59:27 +0000 (10:59 +0100)
Expose meta_data_toc function in utils_cache.

177 files changed:
.travis.yml
AUTHORS
CODEOWNERS
ChangeLog
Makefile.am
README
bindings/perl/lib/Collectd/Plugins/OpenVZ.pm
configure.ac
contrib/collectd_network.py
contrib/collection3/share/navigate.js
contrib/php-collection/browser.js
contrib/redhat/collectd.spec
src/aggregation.c
src/amqp.c
src/amqp1.c
src/apache.c
src/aquaero.c
src/ascent.c
src/barometer.c
src/battery.c
src/bind.c
src/ceph.c
src/check_uptime.c [new file with mode: 0644]
src/chrony.c
src/collectd-snmp.pod
src/collectd.conf.in
src/collectd.conf.pod
src/collectdctl.c
src/collectdmon.c
src/connectivity.c [new file with mode: 0644]
src/contextswitch.c
src/cpu.c
src/cpusleep.c
src/cpython.h
src/curl.c
src/curl_json.c
src/curl_xml.c
src/daemon/cmd.c
src/daemon/collectd.c
src/daemon/configfile.c
src/daemon/globals.c
src/daemon/plugin.c
src/daemon/plugin.h
src/daemon/plugin_mock.c
src/daemon/utils_cache.c
src/daemon/utils_cache.h
src/daemon/utils_random.h
src/disk.c
src/dns.c
src/dpdkevents.c
src/dpdkstat.c
src/email.c
src/exec.c
src/gmond.c
src/gpu_nvidia.c
src/grpc.cc
src/intel_rdt.c
src/intel_rdt_test.c
src/interface.c
src/ipc.c
src/ipmi.c
src/iptables.c
src/ipvs.c
src/java.c
src/libcollectdclient/client.c
src/libcollectdclient/network_parse.c
src/libcollectdclient/network_parse_test.c
src/liboconfig/aux_types.h
src/load.c
src/logfile.c
src/lpar.c
src/lua.c
src/lvm.c [deleted file]
src/madwifi.c
src/madwifi.h
src/match_empty_counter.c
src/match_regex.c
src/mcelog.c
src/memcached.c
src/memory.c
src/mic.c
src/modbus.c
src/mqtt.c
src/mysql.c
src/netapp.c
src/netlink.c
src/network.c
src/network_test.c [new file with mode: 0644]
src/nfs.c
src/nginx.c
src/notify_desktop.c
src/notify_email.c
src/nut.c
src/onewire.c
src/openldap.c
src/openvpn.c
src/oracle.c
src/ovs_events.c
src/ovs_stats.c
src/pcie_errors.c
src/perl.c
src/postgresql.c
src/powerdns.c
src/processes.c
src/procevent.c [new file with mode: 0644]
src/protocols.c
src/python.c
src/redis.c
src/routeros.c
src/rrdcached.c
src/rrdtool.c
src/sensors.c
src/serial.c
src/sigrok.c
src/smart.c
src/snmp.c
src/snmp_agent.c
src/statsd.c
src/swap.c
src/sysevent.c [new file with mode: 0644]
src/syslog.c
src/tail_csv.c
src/tape.c
src/tcpconns.c
src/teamspeak2.c
src/ted.c
src/thermal.c
src/threshold.c
src/turbostat.c
src/types.db
src/uptime.c
src/users.c
src/utils/cmds/cmds_test.c
src/utils/common/common.c
src/utils/common/common.h
src/utils/common/common_test.c
src/utils/config_cores/config_cores.c
src/utils/db_query/db_query.c
src/utils/dns/dns.c
src/utils/dns/dns.h
src/utils/dpdk/dpdk.c
src/utils/format_graphite/format_graphite_test.c
src/utils/format_json/format_json.c
src/utils/format_json/format_json_test.c
src/utils/format_stackdriver/format_stackdriver.c
src/utils/format_stackdriver/format_stackdriver_test.c
src/utils/gce/gce.c
src/utils/latency/latency.c
src/utils/latency/latency.h
src/utils/latency/latency_config.c
src/utils/latency/latency_test.c
src/utils/mount/mount.c
src/utils/mount/mount.h
src/utils/oauth/oauth.c
src/utils/oauth/oauth_test.c
src/utils/ovs/ovs.c
src/utils/proc_pids/proc_pids.c
src/utils/proc_pids/proc_pids.h
src/utils/proc_pids/proc_pids_test.c
src/utils/rrdcreate/rrdcreate.c
src/utils/taskstats/taskstats.c
src/utils_tail_match.h
src/uuid.c
src/varnish.c
src/virt.c
src/vmem.c
src/vserver.c
src/write_graphite.c
src/write_http.c
src/write_kafka.c
src/write_mongodb.c
src/write_prometheus.c
src/write_redis.c
src/write_riemann.c
src/write_stackdriver.c
src/zfs_arc.c
version-gen.sh

index 4ba4e2a..45fb898 100644 (file)
@@ -12,17 +12,21 @@ env:
 matrix:
   include:
     - os: osx
-      osx_image: xcode10.1
+      osx_image: xcode11.2
       compiler: clang
+      jdk: openjdk10
       env:
         - CXX=clang++
         - PATH="/usr/local/opt/mysql-client/bin:$PATH"
+        - JAVA_HOME="/Library/Java/JavaVirtualMachines/openjdk-13.jdk/Contents/Home"
     - os: linux
       dist: xenial
       compiler: clang
+      jdk: openjdk10
     - os: linux
       dist: xenial
       compiler: gcc
+      jdk: openjdk10
 
 before_install:
   # When building the coverity_scan branch, allow only the first job to continue to avoid travis-ci/travis-ci#1975.
@@ -32,7 +36,10 @@ before_script: autoreconf -vif
 
 script:
   - if [[ "${TRAVIS_BRANCH}" == "coverity_scan" ]]; then exit 0; fi
+  - type pkg-config
+  - pkg-config --list-all | sort -u
   - ./configure
+  - cat config.log
   - make distcheck DISTCHECK_CONFIGURE_FLAGS="--disable-dependency-tracking --enable-debug"
 
 addons:
@@ -56,7 +63,6 @@ addons:
     - liblua50-dev
     - liblua5.1-0-dev
     - liblua5.2-dev
-    - liblvm2-dev
     - libmemcached-dev
     - libmicrohttpd-dev
     - libmnl-dev
@@ -78,7 +84,6 @@ addons:
     - libsensors4-dev
     - libsigrok-dev
     - libsnmp-dev
-    - libstatgrab-dev
     - libtokyocabinet-dev
     - libtokyotyrant-dev
     - libudev-dev
@@ -115,9 +120,10 @@ addons:
     - liboping
     - libpcap
     - librdkafka
-    - libstatgrab
     - libvirt
+    - libxml2
     - lua
+    - mongo-c-driver
     - mosquitto
     - mysql-client
     - net-snmp
diff --git a/AUTHORS b/AUTHORS
index d05b86f..d8548d1 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -56,11 +56,23 @@ Amit Gupta <amit.gupta221 at gmail.com>
 Andreas Henriksson <andreas at fatal.se>
  - libmnl support in the netlink plugin.
 
+Andrew Bays <abays at redhat.com>
+ - connectivity plugin.
+ - procevent plugin.
+ - sysevent plugin.
+ - connectivity plugin.
+
 Andy Parkins <andyp at fussylogic.co.uk>
  - battery plugin: sysfs code.
 
+Aneesh Puttur <aputtur at redhat.com>
+ - connectivity plugin.
+
 Andy Smith <ansmith at redhat.com>
  - AMQP 1.0 plugin.
+Aneesh Puttur <aputtur at redhat.com>
+ - connectivity plugin.
 
 Anthony Dewhurst <dewhurst at gmail.com>
  - zfs_arc plugin.
index 55fbd04..5a2fe30 100644 (file)
@@ -4,7 +4,6 @@
 # These owners will be the default owners for everything in the repo. Unless a
 # later match takes precedence, # @trusted-contributors will be requested for
 # review when someone opens a pull request.
-*       @trusted-contributors
 
 /src/intel_pmu.c       @kwiatrox @sunkuranganath
 /src/intel_rdt.c       @kwiatrox @sunkuranganath
@@ -13,3 +12,7 @@
 /src/virt.c            @anaudx @rjablonx
 # TODO(#2926): Add the following owners:
 #/src/redfish.c                @kkepka @mkobyli
+
+# Order is important; the last matching pattern takes the most
+# precedence.
+*       @trusted-contributors
index 7ea5a07..e558a26 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,300 @@
+2019-10-01, Version 5.9.2
+       * syslog plugin: Don't fail if syslog loglevel doesn't match. Thanks to
+         Fabien Wernli. #3236 #3238
+       * collectd: Fix ssnprintf wrapper. Thanks to Fabien Wernli. #3237
+       * rdt plugin: Fix compile time issues. Thanks to Matthias Runge. #3245
+
+2019-07-24, Version 5.9.1
+       * collectd: redhat spec: fix build due to new upstream plugins. Thanks
+         to Fabien Wernli. #3175
+       * collectd: regex match: Fix unexpected match with empty meta data .
+         Thanks to Takuro Ashie. #3178
+       * collectd: Fix return value or loglevel for several plugins. Thanks to
+         Fabien Wernli. #3182
+       * collectd: Add standard include early or _FILE_OFFSET_BITS will have
+         definition … . Thanks to Dagobert Michelsen. #3193
+       * collectd: Use GCC-specific flags only when compiling with GCC. Thanks
+         to Dagobert Michelsen. #3195
+       * Use test_utils_proc_pids only when compiling the plugin that uses it.
+         Thanks to Dagobert Michelsen. #3197
+       * DNS plugin: Do not use headers from glibc. Thanks to Pavel Rochnyak.
+         #3156, #3145
+       * collectd: Add missing definitions for libnetsnmpagent. Thanks to
+         Dagobert Michelsen. #3203
+       * collectd: Move Makefile rules for pid_test inside conditional for
+         code. Thanks to Dagobert Michelsen. #3206
+       * collectd: Recover setlocale() call in src/daemon/collectd.c do_init().
+         Thanks to Pavel Rochnyak. #3214, #3181
+       * collectd: Add snprintf wrapper for GCC 8.2/3. Thanks to zebity. #3153,
+         #2895, #3038
+       * collectd: Fix bug that leads to CPPFLAGS gets overridden with CFLAGS
+         when libxmms is enabled. Thanks to Dagobert Michelsen. #3207
+       * Write_Riemann plugin: Copy MetaData to Riemann events in
+         write_riemann. Thanks to Romain Tartière. #3158
+       * virt plugin: Fix memory leak with libvirt MetadataXPath enabled.
+         Thanks to Pavel Rochnyak. #3225, #3230
+
+2019-06-13, Version 5.9.0
+       * Build System: configure.ac: option "--with-libxml2" has been added.
+         Thanks to Dimitrios Apostolou, Pavel Rochnyak. #2864
+       * Build System: configure.ac: run dpdk build tests only if pkgconfig
+         fails. Thanks to Luca Boccassi, Pavel Rochnyak. #3015
+       * Build System: The "df" plugin is now built when "getmntent_r()" is
+         available. Thanks to Florian Forster. #3095
+       * Build System: The ability to turn on collectd "debug" feature in RPMs
+         has been added. Thanks to dehotot. #2755
+       * collectd: A new "UNKNOWN" state as the initial state of metrics has
+         been added. Thanks to Luis Fernández Álvarez, Florian Forster. #2976
+       * collectd: Base port to Windows. Thanks to Sean Campbell. #2810
+       * collectd: Code ownership of five plugins has been handed out to folks
+         from Intel. Thanks to Florian Forster. #3053
+       * collectd: config parser: Improved error reporting on global options.
+         Thanks to Pavel Rochnyak. #2813
+       * collectd: daemon: make plugin_dispatch_multivalue() obey write queue
+         limits. Thanks to Adam Romanek. #2898
+       * collectd: Macros "STRERROR" and "STRERRNO" have been added. Thanks to
+         Florian Forster. #2519
+       * collectd: Plugin name field has been added to plugin context to
+         improve error reporting. Thanks to Pavel Rochnyak. #2821
+       * collectd-tg: Use "CLOCK_REALTIME" for collectd-tg times. Thanks to
+         Andrew Bays. #2837
+       * tree-wide: Don't initialize static pointers to NULL, use "bool" from
+         "stdbool.h" (instead of "_Bool"). Thanks to Ruben Kerkhof. #2771,
+         #2772
+       * tree-wide: Replace zu with "PRIsz" and llu with "PRIu64". Thanks to
+         Sean Campbell. #2512
+       * tree-wide: Use interval value from plugin context, do not set
+         "vl->interval" in plugins more. Thanks to Pavel Rochnyak. #2847
+       * tree-wide: Utilities and libraries have been moved to "src/utils/".
+         Thanks to Florian Forster. #2961
+       * AMPQ1 plugin: A new plugin to write to amqp1 protocol. Thanks to Andy
+         Smith. #2618
+       * Chrony plugin: Ignoring late responses has been added. Thanks to
+         Miroslav Lichvar, Pavel Rochnyak. #2896
+       * CPUFreq plugin: Read number of p-state transitions and time spent in
+         each p-state. Thanks to Sexton Rory. #2803
+       * cURL, cURL-XML plugins: Option "Interval" has been added. Thanks to
+         Pavel Rochnyak. #2847
+       * Disk plugin: Report number of in progress disk IO requests on FreeBSD.
+         Thanks to Nathan Huff. #2878
+       * Exec plugin: Dynamic allocation of grname buffer has been added.
+         Thanks to sreedi, Florian Forster. #2937
+       * GPU NVML plugin: New plugin to collect NVIDIA GPU stats. Thanks to
+         Evgeny Naumov. #2923
+       * gRPC plugin: The "VerifyPeer" option for servers has been added.
+         Thanks to Florian Forster. #2593
+       * Intel RDT plugin: Support for groups of PIDs has been added. Thanks to
+         Wojciech Andralojc, Mateusz Starzyk, Michal Aleksinski. #2891
+       * IPMI plugin: Config options "SELSensor" and "SELIgnoreSelected" have
+         been added. Thanks to Mariusz Szafranski. #2796
+       * Modbus plugin: Support for 64 bit vals has been added, support for
+         CDAB endian 32-bit modbus polls has been added. Thanks to Anthony
+         Vickers, PJ Bostley. #2670, #2660
+       * Modbus plugin: The "Scale" and "Shift" metrics have been added. Thanks
+         to cekstam. #2729
+       * Netlink plugin: Handle new counter from Linux kernel version 4.6+.
+         Thanks to Pavel Rochnyak. #2767
+       * Network plugin: Option "BindAddress" has been added. Thanks to Ofir
+         Hermesh. #2831
+       * Ping plugin: An "AddressFamily" configuration option has been added.
+         Thanks to 依云 lilydjwg. #2961
+       * OVS Stats plugin: Extended metrics "ovs-dpdk" have been added. Thanks
+         to Matteo Croce, Ryan McCabe. #3000
+       * OVS Stats plugin: Support of bond interface and a "InterfaceStats"
+         config option have been added. Thanks to Andrew Bays. #2880
+       * PCIe Errors plugin: New plugin to read "PCIe" errors. Thanks to Kamil
+         Wiatrowski. #2733
+       * Processes plugin: Support for Linux Delay Accounting has been added.
+         Thanks to Florian Forster. #2598
+       * Redis plugin: Keyspace "hitratio" metric has been added, metric
+         "operations_per_second" has been removed, an option for connecting via
+         UNIX socket has been added. Thanks to Pavel Rochnyak. #2838, #2845,
+         #2904
+       * RouterOS plugin: Support for temperature and voltage data has been
+         added, use MAC-address when Radio-name is missing. Thanks to Pavel
+         Rochnyak. #2851, #2854
+       * RRDCacheD plugin: Time resolution has been improved to microseconds.
+         Thanks to Brian T. O'Neill. #3065
+       * Sensors plugin: Checks for upper limit of "SENSORS_API_VERSION" have
+         been removed, support for libsensors older than 3.0.0 has been
+         dropped. Thanks to Pavel Rochnyak. #3013, #3014
+       * SNMP plugin: New options "PluginInstance", "TypeInstance",
+         "TypeInstanceOID", "PluginInstanceOID", "FilterOID", "FilterValues"
+         and "FilterIgnoreSelected" have been added. Thanks to Pavel Rochnyak.
+         #2817, #2819
+       * SNMP Agent plugin: Multiple key indexes to snmp table and other new
+         features have been added, refactoring, coverity scan issues have been
+         fixed. Thanks to Marcin Mozejko. #2702, #2844
+       * Swap plugin: Support for Linux 2.4 has been dropped. Thanks to Pavel
+         Rochnyak. #2979
+       * Turbostat plugin: Configuration option "RestoreAffinityPolicy" has
+         been added. Thanks to Pablo Llopis. #2627
+       * Turbostat plugin: New metrics "P-states", "Turboboost", "Platform
+         TDP", "Uncore bus ratio" have been added. Thanks to Sexton Rory. #2806
+       * Turbostat plugin: Support of reporting GPU power on SKL has been
+         added. Thanks to Gordon Kelly. #2605
+       * virt plugin: Allow read "Hostname" from libvirt metadata. Thanks to
+         Mehdi ABAAKOUK. #2807
+       * virt plugin: Block info statistics for disk devices have been added.
+         Thanks to Radoslaw Jablonski. #2874
+       * Wireless plugin: A "bitrate" metric has been added. Thanks to Florian
+         Forster. #2950
+       * Write Graphite, Write Kafka plugins: Support for Graphite 1.1+ tag has
+         been added. Thanks to Dan Cech. #2631
+       * Write Prometheus plugin: Option "Host" has been added. Thanks to Pavel
+         Rochnyak. #2969
+       * Write Stackdriver plugin: New plugin to write to Google Stackdriver
+         Monitoring. Thanks to Florian Forster. #2472
+       * Write Syslog plugin: "write_syslog" plugin writes values lists as
+         syslog messages. Thanks to Shirly Radco. #3019
+       * Build System: A warning that pkgdatadir and pkglibdir were previously
+         defined has been fixed, additional plugins have been enabled,
+         GNULIB_DIR has been added to LDFLAGS in configure.ac on Windows.
+         Thanks to Sean Campbell. #2907, #2885, #2882
+       * Build System: Including "utils/mount/mount.h" has been fixed. Thanks
+         to Florian Forster. #3097
+       * Build System: The amount of output from ./configure has been reduced,
+         rendering of collectd-lua(5) manpage has been fixed, don't hide errors
+         when creating manpage. Thanks to Ruben Kerkhof. #3086, #3088, #3092
+       * collectd: A bug in "c_avl_iterator_prev" has been fixed. Thanks to
+         volth. #2917
+       * collectd: A stringop compiler warning has been fixed. Thanks to Ruben
+         Kerkhof, Juan Osorio Robles. #3021
+       * collectd: An invalid memory access in the "strjoin()" function has
+         been fixed. Thanks to Florian Forster. #3063
+       * collectd: collectd binary has been refactored. Thanks to Sean
+         Campbell, Sebastian Harl. #2745
+       * collectd: collectdmon cannot exit command line options parse loop has
+         been fixed. Thanks to takahashi-tsc. #2774
+       * collectd: Endianness checks for AIX have been added, gcc issue on Mac
+         byteorder has been fixed, fallback for endianness conversion has been
+         added. Thanks to Dagobert Michelsen. #2761, #2741, #2717
+       * collectd: Handle failure of simple config callbacks. Thanks to Ruben
+         Kerkhof. #3085
+       * collectd: Include "kstat.h" if available to provide "kstat_ctl_t",
+         include "kstat.h" when available. Thanks to Dagobert Michelsen. #2716,
+         #2711
+       * collectd: Parsing option for avoiding making BaseDir has been fixed.
+         Thanks to Mariusz Białończyk. #2856
+       * collectd: Remove empty "cmd_listval_t" data structure and related
+         no-op code. Thanks to Pavel Rochnyak. #2779
+       * collectd: src/daemon/plugin.c: Refactor plugin_load_file(),
+         src/utils_format_json.c: Remove chatty debug messages. Thanks to
+         Florian Forster. #2558, #2938
+       * collectd: Stop poisoning function in debug mode. Thanks to Ruben
+         Kerkhof. #2804
+       * collectd: The number of allocations when parsing types.db has been
+         reduced. Thanks to Ruben Kerkhof. #3091
+       * collectd: The organization of the source repository has been improved.
+         Thanks to Florian Forster. #2961
+       * collectd: Typos have been fixed. Thanks to Florian Forster, Jakub
+         Jankowski, William Pursell. #2944, #2692, #2643
+       * tree-wide: cleanup: cf_util_get* instead of local copy in plugins,
+         prefixed error reporting. Thanks to Pavel Rochnyak. #2833
+       * tree-wide: Some style issues have been fixed. Thanks to Ruben Kerkhof.
+         #3022
+       * tree-wide: "sstrerror()" has been replaced with "STRERRNO". Thanks to
+         Pavel Rochnyak. #2735
+       * AMQP1 plugin: Potential memory leaks found via scan-build have been
+         fixed, a typo in error log message has been fixed, cleanups. Thanks to
+         Andy Smith, Andrew Bays, Ruben Kerkhof. #2802, #2876, #2797
+       * Barometer plugin: Support to "libi2c-4.0" has been added. Thanks to
+         Pavel Rochnyak. #2783
+       * DBI, Oracle, PostgreSQL plugins: Fixes and improvements. Thanks to
+         Pavel Rochnyak. #1705
+       * Disk plugin: "HAVE_UDEV_H" has been changed to "HAVE_LIBUDEV_H".
+         Thanks to Dylan Stephano-Shachter. #2668
+       * Disk plugin: In linux, reset the disk when it disappears from
+         "/proc/diskstats". Thanks to Nikita Kozlov, Pavel Rochnyak. #2551
+       * DPDK Events, DPDK Stats plugins: Buffer size for parsing lcores has
+         been increased, a deprecation warning has been fixed, runtime config
+         file path has been fixed. Thanks to Kevin Laatz. #2722, #2840, #2924
+       * DPDK Stats plugin: A compilation issue has been fixed. Thanks to
+         Volodymyr Mytnyk. #2524
+       * GPS plugin: Build with gpsd version 3.18 has been fixed. Thanks to
+         Baruch Siach. #2947
+       * Intel RDT plugin: Compiler warnings have been fixed. Thanks to Ruben
+         Kerkhof. #3104
+       * Log Logstash plugin: Non-portable struct initialization with "{}" has
+         been fixed. Thanks to Florian Forster. #2988
+       * LUA plugin: A memory leak has been fixed. Thanks to Ruben Kerkhof.
+         #3090
+       * MySQL plugin: Properly cleanup dropped MySQL connections. Thanks to
+         Dhrupad Bhardwaj. #2704
+       * Netlink plugin: Truncation warnings have been fixed. Thanks to Ruben
+         Kerkhof. #2777
+       * NFS plugin: Message "Unexpected number of fields for NFSv4 server
+         statistics: 62" has been fixed. Thanks to Yedidyah Bar David. #2076
+       * NFS plugin: Number of fields for "NFSv4" has been fixed. Thanks to
+         Jan-Philipp Litza. #2915
+       * Notify Email plugin: All notification parameters have been included
+         into email. Thanks to Pavel Rochnyak. #2834
+       * NTPd plugin: Don't treat normal peers as refclocks, skip "0.0.0.0"
+         hosts in ntpd plugin. Thanks to Pavel Rochnyak, Ivan Kurnosov. #2822,
+         #2376
+       * OAuth plugin: src/utils_oauth.c: Renew OAuth tokens 30 seconds before
+         they expire. Thanks to Florian Forster. #2970
+       * OVS Stats plugin: A macro to populate counters list has been added,
+         value of "OpenFlow" has been corrected. Thanks to Matteo Croce. #2966,
+         #2963
+       * OVS Stats plugin: Code style, cleanup and improvements. Thanks to
+         Pavel Rochnyak. #3011, #3012
+       * OVS Stats, OVS Events plugins: utils_ovs: Avoid potential access of
+         freed memory, fixes. Thanks to Ciara Loftus, Mark Kavanagh. #2801,
+         #2731
+       * Processes plugin: Compilation has been fixed when ps_delay() is not
+         used. Thanks to Pavel Rochnyak. #2610
+       * Python plugin: A compilation warning with Python 3.7 has been fixed.
+         Thanks to Manoj Srivastava. #3042
+       * Redis plugin: Bugfixes, extended error reporting, persistent
+         connections and parallel polling, ability to select db for queries has
+         been fixed. Thanks to Pavel Rochnyak, skob. #2826, #2789
+       * Router OS plugin: Unset radio-name showing up as "(null)" has been
+         fixed. Thanks to melak. #2740
+       * RRDCacheD plugin: Cleanup rrdcached plugin a bit. Thanks to Pavel
+         Rochnyak. #3080
+       * RRDTool plugin: Error reporting has been extended. Thanks to Pavel
+         Rochnyak. #2825
+       * Sensors plugin: Support for humidity sensors has been added. Thanks to
+         Sarah Fischmann. #2913
+       * Sensu, OVS Stat, Turbostat, virt, OAuth, Write Prometheus, Intel RDT
+         plugins: Compiler warnings have been fixed. Thanks to Ruben Kerkhof.
+         #3093, #3098, #3099, #3100, #3102, #3103, #3104
+       * virt plugin: Code "do {} while(0)" around macro has been removed.
+         Thanks to Florian Forster. #2579
+       * virt plugin: Compiler warnings, a segfault in libvirt, typo in error
+         messages have been fixed. Thanks to Antoine Naud, Ruben Kerkhof, sarah
+         niuxu18. #2808, #2919, #2957
+       * virt plugin: Optional "virDomainGetCPUStats()" has been removed from
+         main flow, cleanup. Thanks to Pavel Rochnyak. #2972, #2978
+       * virt plugin: Tracking of VM state changes has been fixed. Thanks to
+         Radoslaw Jablonski. #2701
+       * Write MongoDB plugin: Plugin dependencies have been fixed. Thanks to
+         Pavel Rochnyak. #3010
+       * Write Prometheus plugin: A compilation issue on Mac OS X has been
+         fixed. Thanks to Florian Forster. #3059
+       * Write Redis plugin: Bug ""max_set_duration" deletes unexpected data"
+         has been fixed. Thanks to takahashi-tsc. #2773
+       * Write Stackdriver plugin: Potential NULL dereference and error
+         reporting have been fixed. Thanks to Florian Forster. #2960
+       * collectd.conf(5): a typo has been fixed, the tail plugin's
+         documentation has been improved. Thanks to Ruben Kerkhof, Florian
+         Forster. #3087, #2994
+       * collectd.conf.pod: virt: "Instances" option has been documented, a
+         clarifying example has been added. Thanks to Pavel Rochnyak, Fabien
+         Wernli. #2990, #2903
+       * collectd-python: "Import" configuration option has been documented.
+         Thanks to Tyler Harper. #2985
+       * collectd-snmp.pod: Document thread usage correctly. Thanks to Nathan
+         Ward. #3078
+       * CONTRIBUTING.md: Improve wording around ChangeLog; fix example,
+         document the new change log requirement / behavior. Thanks to Florian
+         Forster. #3061, #3054
+       * docs/review_comments.md: document with frequent review comments has
+         been started. Thanks to Florian Forster. #2964
+       * README: Include compiler defenses suggestion, do not point users to
+         non-existing file. Thanks to Kevin Laatz, Ruben Kerkhof. #2721, #2045
+
 2018-10-23, Version 5.8.1
        * collectd: Fix "BaseDir" option. Thanks to Mariusz Białończyk and
          Pavel Rochnyak. #2857
index 0821283..258603f 100644 (file)
@@ -136,6 +136,7 @@ noinst_LTLIBRARIES = \
        libheap.la \
        libignorelist.la \
        liblatency.la \
+       libllist.la \
        liblookup.la \
        libmetadata.la \
        libmount.la \
@@ -159,8 +160,7 @@ check_PROGRAMS = \
        test_utils_time \
        test_utils_vl_lookup \
        test_libcollectd_network_parse \
-       test_utils_config_cores \
-       test_utils_proc_pids
+       test_utils_config_cores
 
 
 TESTS = $(check_PROGRAMS)
@@ -245,8 +245,6 @@ collectd_SOURCES = \
        src/daemon/utils_cache.h \
        src/daemon/utils_complain.c \
        src/daemon/utils_complain.h \
-       src/daemon/utils_llist.c \
-       src/daemon/utils_llist.h \
        src/daemon/utils_random.c \
        src/daemon/utils_random.h \
        src/daemon/utils_subst.c \
@@ -266,6 +264,7 @@ collectd_LDADD = \
        libavltree.la \
        libcommon.la \
        libheap.la \
+       libllist.la \
        liboconfig.la \
        -lm \
        $(COMMON_LIBS) \
@@ -377,11 +376,6 @@ test_utils_config_cores_SOURCES = \
        src/testing.h
 test_utils_config_cores_LDADD = libplugin_mock.la
 
-test_utils_proc_pids_SOURCES = \
-       src/utils/proc_pids/proc_pids_test.c \
-       src/testing.h
-test_utils_proc_pids_LDADD = libplugin_mock.la
-
 libavltree_la_SOURCES = \
        src/utils/avltree/avltree.c \
        src/utils/avltree/avltree.h
@@ -399,6 +393,10 @@ libignorelist_la_SOURCES = \
        src/utils/ignorelist/ignorelist.c \
        src/utils/ignorelist/ignorelist.h
 
+libllist_la_SOURCES = \
+       src/daemon/utils_llist.c \
+       src/daemon/utils_llist.h
+
 libmetadata_la_SOURCES = \
        src/utils/metadata/meta_data.c \
        src/utils/metadata/meta_data.h
@@ -774,6 +772,21 @@ chrony_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 chrony_la_LIBADD = -lm
 endif
 
+if BUILD_PLUGIN_CHECK_UPTIME
+pkglib_LTLIBRARIES += check_uptime.la
+check_uptime_la_SOURCES = src/check_uptime.c
+check_uptime_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_CONNECTIVITY
+pkglib_LTLIBRARIES += connectivity.la
+connectivity_la_SOURCES = src/connectivity.c
+connectivity_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMNL_CFLAGS)
+connectivity_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+connectivity_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+connectivity_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS) $(BUILD_WITH_LIBMNL_LIBS) libignorelist.la
+endif
+
 if BUILD_PLUGIN_CONNTRACK
 pkglib_LTLIBRARIES += conntrack.la
 conntrack_la_SOURCES = src/conntrack.c
@@ -1090,6 +1103,13 @@ test_plugin_intel_rdt_LDFLAGS = $(PLUGIN_LDFLAGS)
 test_plugin_intel_rdt_LDADD = liboconfig.la libplugin_mock.la
 check_PROGRAMS += test_plugin_intel_rdt
 TESTS += test_plugin_intel_rdt
+
+test_utils_proc_pids_SOURCES = \
+       src/utils/proc_pids/proc_pids_test.c \
+       src/testing.h
+test_utils_proc_pids_LDADD = libplugin_mock.la
+check_PROGRAMS += test_utils_proc_pids
+TESTS += test_utils_proc_pids
 endif
 
 if BUILD_PLUGIN_INTERFACE
@@ -1206,14 +1226,6 @@ lua_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 lua_la_LIBADD = $(BUILD_WITH_LIBLUA_LIBS)
 endif
 
-if BUILD_PLUGIN_LVM
-pkglib_LTLIBRARIES += lvm.la
-lvm_la_SOURCES = src/lvm.c
-lvm_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBLVM2APP_CPPFLAGS)
-lvm_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBLVM2APP_LDFLAGS)
-lvm_la_LIBADD = $(BUILD_WITH_LIBLVM2APP_LIBS)
-endif
-
 if BUILD_PLUGIN_MADWIFI
 pkglib_LTLIBRARIES += madwifi.la
 madwifi_la_SOURCES = \
@@ -1390,6 +1402,27 @@ network_la_CPPFLAGS += $(GCRYPT_CPPFLAGS)
 network_la_LDFLAGS += $(GCRYPT_LDFLAGS)
 network_la_LIBADD += $(GCRYPT_LIBS)
 endif
+
+test_plugin_network_SOURCES = \
+       src/network_test.c \
+       src/utils_fbhash.c \
+       src/daemon/configfile.c \
+       src/daemon/types_list.c
+test_plugin_network_CPPFLAGS = $(AM_CPPFLAGS) $(GCRYPT_CPPFLAGS)
+test_plugin_network_LDFLAGS = $(PLUGIN_LDFLAGS) $(GCRYPT_LDFLAGS)
+test_plugin_network_LDADD = \
+       libavltree.la \
+       liboconfig.la \
+       libplugin_mock.la \
+       libmetadata.la \
+       $(GCRYPT_LIBS)
+if BUILD_WITH_LIBSOCKET
+test_plugin_network_LDADD += -lsocket
+endif
+if BUILD_WITH_LIBNSL
+test_plugin_network_LDADD += -lnsl
+endif
+check_PROGRAMS += test_plugin_network
 endif
 
 if BUILD_PLUGIN_NFS
@@ -1630,6 +1663,14 @@ processes_la_LIBADD += libtaskstats.la
 endif
 endif
 
+if BUILD_PLUGIN_PROCEVENT
+pkglib_LTLIBRARIES += procevent.la
+procevent_la_SOURCES = src/procevent.c
+procevent_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+procevent_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+procevent_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS) libignorelist.la
+endif
+
 if BUILD_PLUGIN_PROTOCOLS
 pkglib_LTLIBRARIES += protocols.la
 protocols_la_SOURCES = src/protocols.c
@@ -1778,6 +1819,14 @@ synproxy_la_SOURCES = src/synproxy.c
 synproxy_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
 
+if BUILD_PLUGIN_SYSEVENT
+pkglib_LTLIBRARIES += sysevent.la
+sysevent_la_SOURCES = src/sysevent.c
+sysevent_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+sysevent_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+sysevent_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS) libignorelist.la
+endif
+
 if BUILD_PLUGIN_SYSLOG
 pkglib_LTLIBRARIES += syslog.la
 syslog_la_SOURCES = src/syslog.c
diff --git a/README b/README
index f28d499..c8be7d3 100644 (file)
--- a/README
+++ b/README
@@ -54,6 +54,9 @@ Features
     - chrony
       Chrony daemon statistics: Local clock drift, offset to peers, etc.
 
+    - connectivity
+      Event-based interface status.
+
     - conntrack
       Number of nf_conntrack entries.
 
@@ -204,10 +207,6 @@ Features
       collectd without the need to start a heavy interpreter every interval.
       See collectd-lua(5) for details.
 
-    - lvm
-      Size of “Logical Volumes” (LV) and “Volume Groups” (VG) of Linux'
-      “Logical Volume Manager” (LVM).
-
     - madwifi
       Queries very detailed usage statistics from wireless LAN adapters and
       interfaces that use the Atheros chipset and the MadWifi driver.
@@ -347,6 +346,9 @@ Features
     - processes
       Process counts: Number of running, sleeping, zombie, ... processes.
 
+    - procevent
+      Listens for process starts and exits via netlink.
+
     - protocols
       Counts various aspects of network protocols such as IP, TCP, UDP, etc.
 
@@ -391,6 +393,9 @@ Features
       Acts as a StatsD server, reading values sent over the network from StatsD
       clients and calculating rates and other aggregates out of these values.
 
+    - sysevent
+      Listens to rsyslog events and submits matched values.
+
     - swap
       Pages swapped out onto hard disk or whatever is called `swap' by the OS..
 
@@ -836,10 +841,6 @@ Prerequisites
     Used by the `lua' plugin. Currently, Lua 5.1 and later are supported.
     <https://www.lua.org/>
 
-  * liblvm2 (optional)
-    Used by the `lvm' plugin.
-    <ftp://sources.redhat.com/pub/lvm2/>
-
   * libmemcached (optional)
     Used by the `memcachec' plugin to connect to a memcache daemon.
     <http://tangent.org/552/libmemcached.html>
index 4c7c3fe..66359da 100644 (file)
@@ -110,9 +110,9 @@ sub cpu_read {
             $v{'type_instance'} = $cpu_instances[$key];
             $v{'values'} = [ $counters[$key] ];
             plugin_dispatch_values(\%v);
+        }
     }
 }
-}
 
 sub df_read {
     my $veid = shift;
@@ -137,7 +137,7 @@ sub df_read {
         $v{'type_instance'} = $val;
         $v{'values'} = [ $parts[5] * ($parts[6] - $parts[7]), $parts[5] * $parts[7] ];
         plugin_dispatch_values(\%v);
-}
+    }
 }
 
 sub load_read {
@@ -180,7 +180,7 @@ sub processes_read {
         $v{'type_instance'} = $key;
         $v{'values'} = [ $ps_states->{$key} ];
         plugin_dispatch_values(\%v);
-}
+    }
 }
 
 sub users_read {
index c95422f..00e1f6a 100644 (file)
@@ -165,6 +165,7 @@ AC_CHECK_HEADERS_ONCE([ \
   kstat.h \
   kvm.h \
   libgen.h \
+  locale.h \
   mntent.h \
   mnttab.h \
   netdb.h \
@@ -635,16 +636,6 @@ fi
 
 # }}}
 
-# For the dns plugin
-AC_CHECK_HEADERS([arpa/nameser.h])
-AC_CHECK_HEADERS([arpa/nameser_compat.h], [], [],
-  [[
-    #if HAVE_ARPA_NAMESER_H
-    # include <arpa/nameser.h>
-    #endif
-  ]]
-)
-
 AC_CHECK_HEADERS([net/if_arp.h], [], [],
   [[
     #if HAVE_SYS_SOCKET_H
@@ -752,33 +743,21 @@ test_cxx_flags() {
 #
 AC_CHECK_FUNCS_ONCE([ \
     asprintf \
-    closelog \
-    getaddrinfo \
-    getgrnam_r \
-    getnameinfo \
+    execvpe \
     getpwnam \
     getpwnam_r \
-    gettimeofday \
     if_indextoname \
-    openlog \
-    regcomp \
-    regerror \
-    regexec \
-    regfree \
-    select \
-    setenv \
     setgroups \
-    strcasecmp \
-    strdup \
-    strncasecmp \
-    sysconf
+    setlocale
   ]
 )
 
 AC_FUNC_STRERROR_R
 
-SAVE_CFLAGS="$CFLAGS"
-CFLAGS="-Wall -Werror"
+if test "x$GCC" = "xyes"; then
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -Wall -Werror"
+fi
 SAVE_LDFLAGS="$LDFLAGS"
 LDFLAGS=""
 if test "x$ac_system" = "xWindows"; then
@@ -879,6 +858,17 @@ AC_CHECK_FUNCS([socket],
 AM_CONDITIONAL([BUILD_WITH_LIBSOCKET], [test "x$socket_needs_socket" = "xyes"])
 AM_CONDITIONAL([BUILD_WITH_GNULIB], [test "x$socket_needs_gnulib" = "xyes"])
 
+AC_CHECK_FUNCS([inet_ntop],
+  [],
+  [
+    AC_CHECK_LIB([nsl], [inet_ntop],
+      [inet_ntop_needs_nsl="yes"],
+      [AC_MSG_ERROR([cannot find inet_ntop() in libnsl])]
+    )
+  ]
+)
+AM_CONDITIONAL([BUILD_WITH_LIBNSL], [test "x$inet_ntop_needs_nsl" = "xyes"])
+
 clock_gettime_needs_posix4="no"
 AC_CHECK_FUNCS([clock_gettime],
   [have_clock_gettime="yes"],
@@ -2732,6 +2722,7 @@ if test "x$withval" != "xno"; then
   else
     AC_MSG_RESULT([no])
     with_libgrpcpp="no (requires C++11 support)"
+    with_libprotobuf="no (<google/protobuf/util/time_util.h> requires C++11 support)"
   fi
 fi
 
@@ -3179,67 +3170,6 @@ AC_SUBST(BUILD_WITH_LIBLUA_CFLAGS)
 AC_SUBST(BUILD_WITH_LIBLUA_LIBS)
 # }}}
 
-# --with-liblvm2app {{{
-AC_ARG_WITH([liblvm2app],
-  [AS_HELP_STRING([--with-liblvm2app@<:@=PREFIX@:>@], [Path to liblvm2app.])],
-  [
-    if test "x$withval" = "xno"; then
-      with_liblvm2app="no"
-    else
-      with_liblvm2app="yes"
-      if test "x$withval" != "xyes"; then
-        with_liblvm2app_cppflags="-I$withval/include"
-        with_liblvm2app_ldflags="-L$withval/lib"
-      fi
-    fi
-  ],
-  [
-    if test "x$ac_system" = "xLinux"; then
-      with_liblvm2app="yes"
-    else
-      with_liblvm2app="no (Linux only library)"
-    fi
-  ]
-)
-
-if test "x$with_liblvm2app" = "xyes"; then
-  SAVE_CPPFLAGS="$CPPFLAGS"
-  CPPFLAGS="$CPPFLAGS $with_liblvm2app_cppflags"
-
-  AC_CHECK_HEADERS([lvm2app.h],
-    [with_liblvm2app="yes"],
-    [with_liblvm2app="no (lvm2app.h not found)"]
-  )
-
-  CPPFLAGS="$SAVE_CPPFLAGS"
-fi
-
-if test "x$with_liblvm2app" = "xyes"; then
-  SAVE_CPPFLAGS="$CPPFLAGS"
-  SAVE_LDFLAGS="$LDFLAGS"
-  CPPFLAGS="$CPPFLAGS $with_liblvm2app_cppflags"
-  LDFLAGS="$LDFLAGS $with_liblvm2app_ldflags"
-
-  AC_CHECK_LIB([lvm2app], [lvm_lv_get_property],
-    [with_liblvm2app="yes"],
-    [with_liblvm2app="no (Symbol 'lvm_lv_get_property' not found)"]
-  )
-
-  CPPFLAGS="$SAVE_CPPFLAGS"
-  LDFLAGS="$SAVE_LDFLAGS"
-fi
-
-if test "x$with_liblvm2app" = "xyes"; then
-  BUILD_WITH_LIBLVM2APP_CPPFLAGS="$with_liblvm2app_cppflags"
-  BUILD_WITH_LIBLVM2APP_LDFLAGS="$with_liblvm2app_ldflags"
-  BUILD_WITH_LIBLVM2APP_LIBS="-llvm2app"
-fi
-
-AC_SUBST([BUILD_WITH_LIBLVM2APP_CPPFLAGS])
-AC_SUBST([BUILD_WITH_LIBLVM2APP_LDFLAGS])
-AC_SUBST([BUILD_WITH_LIBLVM2APP_LIBS])
-# }}}
-
 # --with-libmemcached {{{
 AC_ARG_WITH([libmemcached],
   [AS_HELP_STRING([--with-libmemcached@<:@=PREFIX@:>@], [Path to libmemcached.])],
@@ -3868,7 +3798,10 @@ if test "x$with_libnetsnmp" = "xyes"; then
   SAVE_CPPFLAGS="$CPPFLAGS"
   SAVE_LDFLAGS="$LDFLAGS"
   SAVE_LIBS="$LIBS"
-  CPPFLAGS="$CPPFLAGS $with_libnetsnmp_cppflags -Wall -Werror"
+  CPPFLAGS="$CPPFLAGS $with_libnetsnmp_cppflags"
+  if test "x$GCC" = "xyes"; then
+    CPPFLAGS="$CPPFLAGS -Wall -Werror"
+  fi
   LDFLAGS="$LDFLAGS $with_libnetsnmp_ldflags"
   LIBS="$LIBS -lnetsnmp"
 
@@ -3968,7 +3901,13 @@ if test "x$with_libnetsnmpagent" = "xyes"; then
   )
 
   AC_CHECK_LIB([netsnmpagent], [init_agent],
-    [with_libnetsnmpagent="yes"],
+    [
+      # libnetsnmp can be built without mib loading support
+      AC_CHECK_LIB([netsnmp], [get_tree],
+        [with_libnetsnmpagent="yes"],
+        [with_libnetsnmpagent="no (libnetsnmp doesn't support mib loading)"]
+      )
+    ],
     [with_libnetsnmpagent="no (libnetsnmpagent not found)"],
     [$libnetsnmphelpers]
   )
@@ -3977,6 +3916,8 @@ if test "x$with_libnetsnmpagent" = "xyes"; then
 fi
 
 if test "x$with_libnetsnmpagent" = "xyes"; then
+  BUILD_WITH_LIBNETSNMPAGENT_CPPFLAGS="$with_libnetsnmpagent_cppflags"
+  BUILD_WITH_LIBNETSNMPAGENT_LDFLAGS="$with_libnetsnmpagent_ldflags"
   BUILD_WITH_LIBNETSNMPAGENT_LIBS="-lnetsnmpagent $libnetsnmphelpers"
 fi
 
@@ -4331,7 +4272,10 @@ if test "x$with_libperl" = "xyes"; then
   # (see issues #41 and #42)
   SAVE_CFLAGS="$CFLAGS"
   SAVE_LIBS="$LIBS"
-  CFLAGS="$CFLAGS $PERL_CFLAGS -Wall -Werror"
+  CFLAGS="$CFLAGS $PERL_CFLAGS"
+  if test "x$GCC" = "xyes"; then
+    CFLAGS="$CFLAGS -Wall -Werror"
+  fi
   LIBS="$LIBS $PERL_LIBS"
 
   AC_CACHE_CHECK([for broken Perl_load_module()],
@@ -4625,7 +4569,7 @@ if test "x$withval" != "xno"; then
   AC_CHECK_LIB([protobuf], [main],
     [
       SAVE_CPPFLAGS="$CPPFLAGS"
-      CPPFLAGS="$with_libprotobuf_cppflags $PROTOBUF_CFLAGS"
+      CPPFLAGS="-std=c++11 $with_libprotobuf_cppflags $PROTOBUF_CFLAGS"
       if test "x$PROTOBUF_LIBS" = "x"
       then
         PROTOBUF_LIBS="-lprotobuf"
@@ -4767,11 +4711,11 @@ if test "$PYTHON_CONFIG" != ""; then
   if test $? -ne 0; then
     with_libpython="no"
   fi
-  LIBPYTHON_LDFLAGS="`${PYTHON_CONFIG} --ldflags`"
+  LIBPYTHON_LDFLAGS="`${PYTHON_CONFIG} --ldflags --embed`" || LIBPYTHON_LDFLAGS="`${PYTHON_CONFIG} --ldflags`"
   if test $? -ne 0; then
     with_libpython="no"
   fi
-  LIBPYTHON_LIBS="`${PYTHON_CONFIG} --libs`"
+  LIBPYTHON_LIBS="`${PYTHON_CONFIG} --libs --embed`" || LIBPYTHON_LIBS="`${PYTHON_CONFIG} --libs`"
   if test $? -ne 0; then
     with_libpython="no"
   fi
@@ -5455,7 +5399,7 @@ AC_ARG_WITH([libtokyotyrant],
       with_libtokyotyrant="$withval"
     else
       with_libtokyotyrant_cppflags="-I$withval/include"
-      with_libtokyotyrant_ldflags="-L$withval/include"
+      with_libtokyotyrant_ldflags="-L$withval/lib"
       with_libtokyotyrant_libs="-ltokyotyrant"
       with_libtokyotyrant="yes"
     fi
@@ -5574,7 +5518,7 @@ AC_ARG_WITH([libupsclient],
     else if test "x$withval" = "xyes"; then
       with_libupsclient="use_pkgconfig"
     else
-      if test -x "$withval"; then
+      if test -f "$withval" && test -x "$withval"; then
         with_libupsclient_config="$withval"
         with_libupsclient="use_libupsclient_config"
       else if test -x "$withval/bin/libupsclient-config"; then
@@ -5769,7 +5713,7 @@ if test "x$with_libxmms" = "xyes"; then
 fi
 
 if test "x$with_libxmms" = "xyes"; then
-  SAVE_CPPFLAGS="$CFLAGS"
+  SAVE_CPPFLAGS="$CPPFLAGS"
   CPPFLAGS="$with_xmms_cflags"
 
   AC_CHECK_HEADER([xmmsctrl.h],
@@ -6369,6 +6313,7 @@ plugin_battery="no"
 plugin_bind="no"
 plugin_ceph="no"
 plugin_cgroups="no"
+plugin_connectivity="no"
 plugin_conntrack="no"
 plugin_contextswitch="no"
 plugin_cpu="no"
@@ -6409,12 +6354,14 @@ plugin_pcie_errors="no"
 plugin_perl="no"
 plugin_pinba="no"
 plugin_processes="no"
+plugin_procevent="no"
 plugin_protocols="no"
 plugin_python="no"
 plugin_serial="no"
 plugin_smart="no"
 plugin_swap="no"
 plugin_synproxy="no"
+plugin_sysevent="no"
 plugin_tape="no"
 plugin_tcpconns="no"
 plugin_ted="no"
@@ -6451,7 +6398,6 @@ if test "x$ac_system" = "xLinux"; then
   plugin_ipc="yes"
   plugin_irq="yes"
   plugin_load="yes"
-  plugin_lvm="yes"
   plugin_mcelog="yes"
   plugin_memory="yes"
   plugin_nfs="yes"
@@ -6484,6 +6430,11 @@ if test "x$ac_system" = "xLinux"; then
   if test "x$with_libyajl" = "xyes" && test "x$with_libyajl2" = "xyes"; then
     plugin_ovs_events="yes"
     plugin_ovs_stats="yes"
+    plugin_procevent="yes"
+
+    if test "x$with_libmnl" = "xyes"; then
+      plugin_connectivity="yes"
+    fi
   fi
 
   if test "x$have_pci_regs_h" = "xyes"; then
@@ -6597,6 +6548,7 @@ fi
 
 if test "x$with_libyajl" = "xyes"; then
   plugin_ceph="yes"
+  plugin_sysevent="yes"
 fi
 
 if test "x$have_processor_info" = "xyes"; then
@@ -6793,6 +6745,8 @@ AC_PLUGIN([bind],                [$plugin_bind],              [ISC Bind nameserv
 AC_PLUGIN([ceph],                [$plugin_ceph],              [Ceph daemon statistics])
 AC_PLUGIN([cgroups],             [$plugin_cgroups],           [CGroups CPU usage accounting])
 AC_PLUGIN([chrony],              [yes],                       [Chrony statistics])
+AC_PLUGIN([check_uptime],        [yes],                       [Notify about uptime reset])
+AC_PLUGIN([connectivity],        [$plugin_connectivity],      [Network interface up/down events])
 AC_PLUGIN([conntrack],           [$plugin_conntrack],         [nf_conntrack statistics])
 AC_PLUGIN([contextswitch],       [$plugin_contextswitch],     [context switch statistics])
 AC_PLUGIN([cpu],                 [$plugin_cpu],               [CPU usage statistics])
@@ -6836,7 +6790,6 @@ AC_PLUGIN([log_logstash],        [$plugin_log_logstash],      [Logstash json_eve
 AC_PLUGIN([logfile],             [yes],                       [File logging plugin])
 AC_PLUGIN([lpar],                [$with_perfstat],            [AIX logical partitions statistics])
 AC_PLUGIN([lua],                 [$with_liblua],              [Lua plugin])
-AC_PLUGIN([lvm],                 [$with_liblvm2app],          [LVM 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])
@@ -6881,6 +6834,7 @@ AC_PLUGIN([ping],                [$with_liboping],            [Network latency s
 AC_PLUGIN([postgresql],          [$with_libpq],               [PostgreSQL database statistics])
 AC_PLUGIN([powerdns],            [yes],                       [PowerDNS statistics])
 AC_PLUGIN([processes],           [$plugin_processes],         [Process statistics])
+AC_PLUGIN([procevent],           [$plugin_procevent],         [Process event (start, stop) statistics])
 AC_PLUGIN([protocols],           [$plugin_protocols],         [Protocol (IP, TCP, ...) statistics])
 AC_PLUGIN([python],              [$plugin_python],            [Embed a Python interpreter])
 AC_PLUGIN([redis],               [$with_libhiredis],          [Redis plugin])
@@ -6896,6 +6850,7 @@ AC_PLUGIN([snmp_agent],          [$with_libnetsnmpagent],     [SNMP agent plugin
 AC_PLUGIN([statsd],              [yes],                       [StatsD plugin])
 AC_PLUGIN([swap],                [$plugin_swap],              [Swap usage statistics])
 AC_PLUGIN([synproxy],            [$plugin_synproxy],          [Synproxy stats plugin])
+AC_PLUGIN([sysevent],            [$plugin_sysevent],          [rsyslog events])
 AC_PLUGIN([syslog],              [$have_syslog],              [Syslog logging plugin])
 AC_PLUGIN([table],               [yes],                       [Parsing of tabular data])
 AC_PLUGIN([tail],                [yes],                       [Parsing of logfiles])
@@ -7076,11 +7031,13 @@ AC_SUBST([LCC_VERSION_STRING])
 
 AC_CONFIG_FILES([src/libcollectdclient/collectd/lcc_features.h])
 
-AM_CFLAGS="-Wall"
-AM_CXXFLAGS="-Wall"
-if test "x$enable_werror" != "xno"; then
-  AM_CFLAGS="$AM_CFLAGS -Werror"
-  AM_CXXFLAGS="$AM_CXXFLAGS -Werror"
+if test "x$GCC" = "xyes"; then
+  AM_CFLAGS="-Wall"
+  AM_CXXFLAGS="-Wall"
+  if test "x$enable_werror" != "xno"; then
+    AM_CFLAGS="$AM_CFLAGS -Werror"
+    AM_CXXFLAGS="$AM_CXXFLAGS -Werror"
+  fi
 fi
 
 AC_SUBST([AM_CFLAGS])
@@ -7151,7 +7108,6 @@ AC_MSG_RESULT([    libkstat  . . . . . . $with_kstat])
 AC_MSG_RESULT([    libkvm  . . . . . . . $with_libkvm])
 AC_MSG_RESULT([    libldap . . . . . . . $with_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])
@@ -7220,6 +7176,8 @@ AC_MSG_RESULT([    bind  . . . . . . . . $enable_bind])
 AC_MSG_RESULT([    ceph  . . . . . . . . $enable_ceph])
 AC_MSG_RESULT([    cgroups . . . . . . . $enable_cgroups])
 AC_MSG_RESULT([    chrony. . . . . . . . $enable_chrony])
+AC_MSG_RESULT([    check_uptime. . . . . $enable_check_uptime])
+AC_MSG_RESULT([    connectivity. . . . . $enable_connectivity])
 AC_MSG_RESULT([    conntrack . . . . . . $enable_conntrack])
 AC_MSG_RESULT([    contextswitch . . . . $enable_contextswitch])
 AC_MSG_RESULT([    cpu . . . . . . . . . $enable_cpu])
@@ -7263,7 +7221,6 @@ AC_MSG_RESULT([    logfile . . . . . . . $enable_logfile])
 AC_MSG_RESULT([    log_logstash  . . . . $enable_log_logstash])
 AC_MSG_RESULT([    lpar  . . . . . . . . $enable_lpar])
 AC_MSG_RESULT([    lua . . . . . . . . . $enable_lua])
-AC_MSG_RESULT([    lvm . . . . . . . . . $enable_lvm])
 AC_MSG_RESULT([    madwifi . . . . . . . $enable_madwifi])
 AC_MSG_RESULT([    match_empty_counter . $enable_match_empty_counter])
 AC_MSG_RESULT([    match_hashed  . . . . $enable_match_hashed])
@@ -7307,6 +7264,7 @@ AC_MSG_RESULT([    ping  . . . . . . . . $enable_ping])
 AC_MSG_RESULT([    postgresql  . . . . . $enable_postgresql])
 AC_MSG_RESULT([    powerdns  . . . . . . $enable_powerdns])
 AC_MSG_RESULT([    processes . . . . . . $enable_processes])
+AC_MSG_RESULT([    procevent . . . . . . $enable_procevent])
 AC_MSG_RESULT([    protocols . . . . . . $enable_protocols])
 AC_MSG_RESULT([    python  . . . . . . . $enable_python])
 AC_MSG_RESULT([    redis . . . . . . . . $enable_redis])
@@ -7322,6 +7280,7 @@ AC_MSG_RESULT([    snmp_agent  . . . . . $enable_snmp_agent])
 AC_MSG_RESULT([    statsd  . . . . . . . $enable_statsd])
 AC_MSG_RESULT([    swap  . . . . . . . . $enable_swap])
 AC_MSG_RESULT([    synproxy  . . . . . . $enable_synproxy])
+AC_MSG_RESULT([    sysevent. . . . . . . $enable_sysevent])
 AC_MSG_RESULT([    syslog  . . . . . . . $enable_syslog])
 AC_MSG_RESULT([    table . . . . . . . . $enable_table])
 AC_MSG_RESULT([    tail_csv  . . . . . . $enable_tail_csv])
index 809f19d..cb328f2 100644 (file)
@@ -16,7 +16,7 @@
 Collectd network protocol implementation.
 """
 
-import socket,struct,sys
+import socket,struct
 import platform
 if platform.python_version() < '2.8.0':
     # Python 2.7 and below io.StringIO does not like unicode
index 3bfe56e..0cf1513 100644 (file)
@@ -183,12 +183,11 @@ function nav_calculate_offset_x (obj)
 function nav_calculate_event_x (e)
 {
   var pos = 0;
-  var off = 0;
 
   if (!e || !e.target)
     return;
   
-  off = nav_calculate_offset_x (e.target);
+  nav_calculate_offset_x (e.target);
 
   if (e.pageX || e.pageY)
   {
index 4ddc424..09673da 100644 (file)
@@ -106,8 +106,8 @@ function refillSelect(options, select) {
                newOption.setAttribute('style', 'font-style: italic');
                newOption.appendChild(document.createTextNode('- please select -'));
                select.appendChild(newOption);
-               for (i = 0; i < optCnt; i++) {
-                       newOption = document.createElement("option");
+               for (var i = 0; i < optCnt; i++) {
+                       var newOption = document.createElement("option");
                        newOption.value = options[i].firstChild ? options[i].firstChild.data : '';
                        if (keepSelection && newOption.value == oldValue)
                                newOption.setAttribute('selected', 'selected');
@@ -311,7 +311,7 @@ function GraphAppend() {
 function ListOfGraph(response) {
        var graphs = response ? response.getElementsByTagName('graph') : null;
        if (graphs && graphs.length > 0) {
-               for (i = 0; i < graphs.length; i++)
+               for (var i = 0; i < graphs.length; i++)
                        GraphDoAppend(graphs[i].getAttribute('host'), graphs[i].getAttribute('plugin'), graphs[i].getAttribute('plugin_instance'),
                                      graphs[i].getAttribute('type'), graphs[i].getAttribute('type_instance'), graphs[i].getAttribute('timespan'),
                                      graphs[i].getAttribute('tinyLegend') == '1', graphs[i].getAttribute('logarithmic') == '1');
@@ -326,7 +326,7 @@ function GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, l
                var graph_id   = 'graph_'+nextGraphId++;
                var graph_src  = graph_url+'?host='+encodeURIComponent(host)+'&plugin='+encodeURIComponent(plugin)+'&plugin_instance='+encodeURIComponent(pinst)+'&type='+encodeURIComponent(type);
                var graph_alt  = '';
-               var grap_title = '';
+               var graph_title = '';
                if (tinst == '@') {
                        graph_alt   = host+'/'+plugin+(pinst.length > 0 ? '-'+pinst : '')+'/'+type;
                        graph_title = type+' of '+plugin+(pinst.length > 0 ? '-'+pinst : '')+' plugin for '+host;
@@ -346,11 +346,11 @@ function GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, l
                graphList.push(graph_id+' '+encodeURIComponent(graph_alt)+(logarithmic ? '&logarithmic=1' : '')+(tinyLegend ? '&tinylegend=1' : '')+'&timespan='+encodeURIComponent(timespan));
 
                // Graph container
-               newGraph = document.createElement('div');
+               var newGraph = document.createElement('div');
                newGraph.setAttribute('class', 'graph');
                newGraph.setAttribute('id', graph_id);
                // Graph cell + graph
-               newImg = document.createElement('img');
+               var newImg = document.createElement('img');
                newImg.setAttribute('src', graph_src);
                newImg.setAttribute('alt', graph_alt);
                newImg.setAttribute('title', graph_title);
@@ -397,7 +397,7 @@ function GraphToggleTools(graph) {
                document.getElementById('ge_graphid').value = graph;
                document.getElementById('ge_tinylegend').checked = src_url.match(/&tinylegend=1/);
                document.getElementById('ge_logarithmic').checked = src_url.match(/&logarithmic=1/);
-               for (i = 0; i < ts_sel.options.length; i++)
+               for (var i = 0; i < ts_sel.options.length; i++)
                        if (ts_sel.options[i].value == ts) {
                                ts_sel.selectedIndex = i;
                                break;
@@ -513,7 +513,7 @@ function GraphAdjust(graph) {
                                imgs[imgCnt].setAttribute('src', newSrc);
 
                                var myList = Array();
-                               for (i = 0; i < graphList.length; i++)
+                               for (var i = 0; i < graphList.length; i++)
                                        if (graphList[i].substring(0, graphId.length) == graphId && graphList[i].charAt(graphId.length) == ' ') {
                                                newSrc = graphList[i];
                                                newSrc = newSrc.replace(/&logarithmic=[^&]*/, '');
@@ -544,7 +544,7 @@ function GraphRemove(graph) {
                        document.getElementById('nograph').style.display = 'block';
 
                var myList = Array();
-               for (i = 0; i < graphList.length; i++)
+               for (var i = 0; i < graphList.length; i++)
                        if (graphList[i].substring(0, graphId.length) == graphId && graphList[i].charAt(graphId.length) == ' ')
                                continue;
                        else
@@ -558,7 +558,7 @@ function GraphMoveUp(graph) {
        var graphId   = graph == null ? document.getElementById('ge_graphid').value : graph;
        var childCnt  = graphs.childNodes.length;
        var prevGraph = null;
-       for (i = 0; i < childCnt; i++)
+       for (var i = 0; i < childCnt; i++)
                if (graphs.childNodes[i].nodeName == 'div' || graphs.childNodes[i].nodeName == 'DIV') {
                        if (graphs.childNodes[i].id == 'nograph') {
                                // Skip
@@ -590,7 +590,7 @@ function GraphMoveDown(graph) {
        var childCnt  = graphs.childNodes.length;
        var nextGraph = null;
        var myGraph   = null;
-       for (i = 0; i < childCnt; i++)
+       for (var i = 0; i < childCnt; i++)
                if (graphs.childNodes[i].nodeName == 'div' || graphs.childNodes[i].nodeName == 'DIV') {
                        if (graphs.childNodes[i].id == 'nograph') {
                                // Skip
@@ -603,12 +603,12 @@ function GraphMoveDown(graph) {
                                break;
                        }
                }
-       for (i = 0; i < graphList.length; i++)
-               if (graphList[i].substring(0, graphId.length) == graphId && graphList[i].charAt(graphId.length) == ' ') {
-                       if (i+1 < graphList.length) {
-                               var tmp = graphList[i+1];
-                               graphList[i+1] = graphList[i];
-                               graphList[i]   = tmp;
+       for (var j = 0; j < graphList.length; j++)
+               if (graphList[j].substring(0, graphId.length) == graphId && graphList[j].charAt(graphId.length) == ' ') {
+                       if (j+1 < graphList.length) {
+                               var tmp = graphList[j+1];
+                               graphList[j+1] = graphList[i];
+                               graphList[j]   = tmp;
                        }
                        break;
                }
@@ -619,7 +619,7 @@ function GraphListFromCookie(lname) {
        if (document.cookie.length > 0) {
                var cname= 'graphLst'+lname+'=';
                var cookies = document.cookie.split('; ');
-               for (i = 0; i < cookies.length; i++)
+               for (var i = 0; i < cookies.length; i++)
                        if (cookies[i].substring(0, cname.length) == cname)
                                return cookies[i].substring(cname.length).split('/');
        }
@@ -663,7 +663,7 @@ function GraphListRefresh() {
        } else {
                select.removeAttribute('disabled');
                for (i = 0; i < optCnt; i++) {
-                       newOption = document.createElement("option");
+                       var newOption = document.createElement("option");
                        newOption.value = options[i][0];
                        if (newOption.value == oldValue)
                                newOption.setAttribute('selected', 'selected');
@@ -705,7 +705,7 @@ function GraphSave() {
        if (graphList.length > 0) {
                // Save graph list to cookie
                var str = '';
-               for (i = 0; i < graphList.length; i++) {
+               for (var i = 0; i < graphList.length; i++) {
                        var g = graphList[i].indexOf(' ');
                        if (i > 0)
                                str += '/';
@@ -743,7 +743,7 @@ function GraphLoad() {
        // Load graph list from cookie
        var grLst = GraphListFromCookie(cname);
        var oldLength = graphList.length;
-       for (i = 0; i < grLst.length; i++) {
+       for (var i = 0; i < grLst.length; i++) {
                var host        = '';
                var plugin      = '';
                var pinst       = '';
@@ -753,7 +753,7 @@ function GraphLoad() {
                var logarithmic = false;
                var tinyLegend  = false;
                var graph = grLst[i].split('&');
-               for (j = 0; j < graph.length; j++)
+               for (var j = 0; j < graph.length; j++)
                        if (graph[j] == 'logarithmic=1')
                                logarithmic = true;
                        else if (graph[j] == 'tinylegend=1')
index 1ba7d11..864ef1b 100644 (file)
@@ -53,6 +53,7 @@
 %define with_ceph 0%{!?_without_ceph:1}
 %define with_cgroups 0%{!?_without_cgroups:1}
 %define with_chrony 0%{!?_without_chrony:1}
+%define with_connectivity 0%{!?_without_connectivity:1}
 %define with_conntrack 0%{!?_without_conntrack:1}
 %define with_contextswitch 0%{!?_without_contextswitch:1}
 %define with_cpu 0%{!?_without_cpu:1}
@@ -89,7 +90,6 @@
 %define with_log_logstash 0%{!?_without_log_logstash:1}
 %define with_logfile 0%{!?_without_logfile:1}
 %define with_lua 0%{!?_without_lua:1}
-%define with_lvm 0%{!?_without_lvm:1}
 %define with_madwifi 0%{!?_without_madwifi:1}
 %define with_mbmon 0%{!?_without_mbmon:1}
 %define with_mcelog 0%{!?_without_mcelog:1}
 %define with_openvpn 0%{!?_without_openvpn:1}
 %define with_ovs_events 0%{!?_without_ovs_events:1}
 %define with_ovs_stats 0%{!?_without_ovs_stats:1}
+%define with_pcie_errors 0%{!?_without_pcie_errors:1}
 %define with_perl 0%{!?_without_perl:1}
 %define with_pinba 0%{!?_without_pinba:1}
 %define with_ping 0%{!?_without_ping:1}
 %define with_postgresql 0%{!?_without_postgresql:1}
 %define with_powerdns 0%{!?_without_powerdns:1}
 %define with_processes 0%{!?_without_processes:1}
+%define with_procevent 0%{!?_without_procevent:1}
 %define with_protocols 0%{!?_without_protocols:1}
 %define with_python 0%{!?_without_python:1}
 %define with_redis 0%{!?_without_redis:1}
 %define with_statsd 0%{!?_without_statsd:1}
 %define with_swap 0%{!?_without_swap:1}
 %define with_synproxy 0%{!?_without_synproxy:0}
+%define with_sysevent 0%{!?_without_sysevent:1}
 %define with_syslog 0%{!?_without_syslog:1}
 %define with_table 0%{!?_without_table:1}
 %define with_tail 0%{!?_without_tail:1}
 %define with_write_prometheus 0%{!?_without_write_prometheus:1}
 %define with_write_redis 0%{!?_without_write_redis:1}
 %define with_write_riemann 0%{!?_without_write_riemann:1}
+%define with_write_stackdriver 0%{!?_without_write_stackdriver:1}
 %define with_write_sensu 0%{!?_without_write_sensu:1}
 %define with_write_syslog 0%{!?_without_write_syslog:1}
 %define with_write_tsdb 0%{!?_without_write_tsdb:1}
 %define with_xencpu 0%{!?_without_xencpu:0}
 # plugin zone disabled, requires Solaris
 %define with_zone 0%{!?_without_zone:0}
+# plugin gpu_nvidia requires cuda-nvml-dev
+# get it from https://developer.nvidia.com/cuda-downloads
+# then install cuda-nvml-dev-10-1 or other version
+%define with_gpu_nvidia 0%{!?_without_gpu_nvidia:0}
+# not sure why this one's failing
+%define with_write_stackdriver 0%{!?_without_write_stackdriver:0}
 
 # Plugins not buildable on RHEL < 6
 %if 0%{?rhel} && 0%{?rhel} < 6
 %define with_gmond 0
 %define with_iptables 0
 %define with_ipvs 0
-%define with_lvm 0
 %define with_modbus 0
 %define with_netlink 0
 %define with_redis 0
 
 # Plugins not buildable on RHEL < 7
 %if 0%{?rhel} && 0%{?rhel} < 7
+%define with_connectivity 0
 %define with_cpusleep 0
 %define with_gps 0
 %define with_mqtt 0
 %define with_ovs_events 0
 %define with_ovs_stats 0
+%define with_procevent 0
 %define with_redis 0
 %define with_rrdcached 0
+%define with_sysevent 0
 %define with_write_redis 0
 %define with_write_riemann 0
 %define with_xmms 0
 
 Summary:       Statistics collection and monitoring daemon
 Name:          collectd
-Version:       5.7.1
-Release:       9%{?dist}
+Version:       5.9.2
+Release:       2%{?dist}
 URL:           https://collectd.org
 Source:                https://collectd.org/files/%{name}-%{version}.tar.bz2
 License:       GPLv2
@@ -372,6 +384,16 @@ Requires:      %{name}%{?_isa} = %{version}-%{release}
 Chrony plugin for collectd
 %endif
 
+%if %{with_connectivity}
+%package connectivity
+Summary:       Connectivity plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libmnl-devel, yajl-devel
+%description connectivity
+Monitors network interface up/down status via netlink library.
+%endif
+
 %if %{with_curl}
 %package curl
 Summary:       Curl plugin for collectd
@@ -566,17 +588,6 @@ The Lua plugin embeds a Lua interpreter into collectd and exposes the
 application programming interface (API) to Lua scripts.
 %endif
 
-%if %{with_lvm}
-%package lvm
-Summary:       LVM plugin for collectd
-Group:         System Environment/Daemons
-Requires:      %{name}%{?_isa} = %{version}-%{release}
-BuildRequires: lvm2-devel
-%description lvm
-This plugin collects size of “Logical Volumes” (LV) and “Volume Groups” (VG)
-of Linux' “Logical Volume Manager” (LVM).
-%endif
-
 %if %{with_mcelog}
 %package mcelog
 Summary:       Mcelog plugin for collectd
@@ -741,6 +752,16 @@ The Perl plugin embeds a Perl interpreter into collectd and exposes the
 application programming interface (API) to Perl-scripts.
 %endif
 
+%if %{with_pcie_errors}
+%package pcie_errors
+Summary:       PCI Express errors plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+%description pcie_errors
+The pcie_errors plugin collects PCI Express errors from Device Status in Capability
+structure and from Advanced Error Reporting Extended Capability.
+%endif
+
 %if %{with_pinba}
 %package pinba
 Summary:       Pinba plugin for collectd
@@ -774,6 +795,16 @@ The PostgreSQL plugin connects to and executes SQL statements on a PostgreSQL
 database.
 %endif
 
+%if %{with_procevent}
+%package procevent
+Summary:       Processes event plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: yajl-devel
+%description procevent
+Monitors process starts/stops via netlink library.
+%endif
+
 %if %{with_python}
 %package python
 Summary:       Python plugin for collectd
@@ -873,6 +904,16 @@ BuildRequires:     net-snmp-devel
 This plugin for collectd to support AgentX integration.
 %endif
 
+%if %{with_sysevent}
+%package sysevent
+Summary:       Rsyslog event plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: yajl-devel
+%description sysevent
+Monitors rsyslog for system events.
+%endif
+
 %if %{with_varnish}
 %package varnish
 Summary:       Varnish plugin for collectd
@@ -945,6 +986,27 @@ BuildRequires:     riemann-c-client-devel >= 1.6
 The riemann plugin submits values to Riemann, an event stream processor.
 %endif
 
+%if %{with_write_stackdriver}
+%package write_stackdriver
+Summary:       stackdriver plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: curl-devel, yajl-devel, openssl-devel
+%description write_stackdriver
+The write_stackdriver collectd plugin writes metrics to the
+Google Stackdriver Monitoring service.
+%endif
+
+%if %{with_gpu_nvidia}
+%package gpu_nvidia
+Summary:       stackdriver plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: cuda-nvml-dev-10-1
+%description gpu_nvidia
+The gpu_nvidia collectd plugin collects NVidia GPU metrics.
+%endif
+
 %if %{with_xencpu}
 %package xencpu
 Summary:       xencpu plugin for collectd
@@ -1097,6 +1159,12 @@ Collectd utilities
 %define _with_chrony --disable-chrony
 %endif
 
+%if %{with_connectivity}
+%define _with_connectivity --enable-connectivity
+%else
+%define _with_connectivity --disable-connectivity
+%endif
+
 %if %{with_conntrack}
 %define _with_conntrack --enable-conntrack
 %else
@@ -1361,12 +1429,6 @@ Collectd utilities
 %define _with_lua --disable-lua
 %endif
 
-%if %{with_lvm}
-%define _with_lvm --enable-lvm
-%else
-%define _with_lvm --disable-lvm
-%endif
-
 %if %{with_madwifi}
 %define _with_madwifi --enable-madwifi
 %else
@@ -1553,6 +1615,12 @@ Collectd utilities
 %define _with_perl --disable-perl
 %endif
 
+%if %{with_pcie_errors}
+%define _with_pcie_errors --enable-pcie_errors
+%else
+%define _with_pcie_errors --disable-pcie_errors
+%endif
+
 %if %{with_pf}
 %define _with_pf --enable-pf
 %else
@@ -1589,6 +1657,12 @@ Collectd utilities
 %define _with_processes --disable-processes
 %endif
 
+%if %{with_procevent}
+%define _with_procevent --enable-procevent
+%else
+%define _with_procevent --disable-procevent
+%endif
+
 %if %{with_protocols}
 %define _with_protocols --enable-protocols
 %else
@@ -1684,6 +1758,12 @@ Collectd utilities
 %define _with_synproxy --disable-synproxy
 %endif
 
+%if %{with_sysevent}
+%define _with_sysevent --enable-sysevent
+%else
+%define _with_sysevent --disable-sysevent
+%endif
+
 %if %{with_syslog}
 %define _with_syslog --enable-syslog
 %else
@@ -1852,6 +1932,18 @@ Collectd utilities
 %define _with_write_riemann --disable-write_riemann
 %endif
 
+%if %{with_write_stackdriver}
+%define _with_write_stackdriver --enable-write_stackdriver
+%else
+%define _with_write_stackdriver --disable-write_stackdriver
+%endif
+
+%if %{with_gpu_nvidia}
+%define _with_gpu_nvidia --enable-gpu_nvidia
+%else
+%define _with_gpu_nvidia --disable-gpu_nvidia
+%endif
+
 %if %{with_write_sensu}
 %define _with_write_sensu --enable-write_sensu
 %else
@@ -1935,6 +2027,7 @@ Collectd utilities
        %{?_with_ceph} \
        %{?_with_cgroups} \
        %{?_with_chrony} \
+       %{?_with_connectivity} \
        %{?_with_conntrack} \
        %{?_with_contextswitch} \
        %{?_with_cpufreq} \
@@ -1977,7 +2070,6 @@ Collectd utilities
        %{?_with_logfile} \
        %{?_with_lpar} \
        %{?_with_lua} \
-       %{?_with_lvm} \
        %{?_with_madwifi} \
        %{?_with_mbmon} \
        %{?_with_mcelog} \
@@ -2009,12 +2101,14 @@ Collectd utilities
        %{?_with_ovs_events} \
        %{?_with_ovs_stats} \
        %{?_with_perl} \
+       %{?_with_pcie_errors} \
        %{?_with_pf} \
        %{?_with_pinba} \
        %{?_with_ping} \
        %{?_with_postgresql} \
        %{?_with_powerdns} \
        %{?_with_processes} \
+       %{?_with_procevent} \
        %{?_with_protocols} \
        %{?_with_python} \
        %{?_with_redis} \
@@ -2030,6 +2124,7 @@ Collectd utilities
        %{?_with_statsd} \
        %{?_with_swap} \
        %{?_with_synproxy} \
+       %{?_with_sysevent} \
        %{?_with_syslog} \
        %{?_with_table} \
        %{?_with_tail_csv} \
@@ -2060,6 +2155,8 @@ Collectd utilities
        %{?_with_write_prometheus} \
        %{?_with_write_redis} \
        %{?_with_write_riemann} \
+       %{?_with_write_stackdriver} \
+       %{?_with_gpu_nvidia} \
        %{?_with_write_sensu} \
        %{?_with_write_syslog} \
        %{?_with_write_tsdb} \
@@ -2479,6 +2576,11 @@ fi
 %{_libdir}/%{name}/chrony.so
 %endif
 
+%if %{with_connectivity}
+%files connectivity
+%{_libdir}/%{name}/connectivity.so
+%endif
+
 %if %{with_curl}
 %files curl
 %{_libdir}/%{name}/curl.so
@@ -2588,11 +2690,6 @@ fi
 %{_libdir}/%{name}/lua.so
 %endif
 
-%if %{with_lvm}
-%files lvm
-%{_libdir}/%{name}/lvm.so
-%endif
-
 %if %{with_memcachec}
 %files memcachec
 %{_libdir}/%{name}/memcachec.so
@@ -2667,6 +2764,11 @@ fi
 %{_libdir}/%{name}/perl.so
 %endif
 
+%if %{with_pcie_errors}
+%files pcie_errors
+%{_libdir}/%{name}/pcie_errors.so
+%endif
+
 %if %{with_pinba}
 %files pinba
 %{_libdir}/%{name}/pinba.so
@@ -2683,6 +2785,11 @@ fi
 %{_libdir}/%{name}/postgresql.so
 %endif
 
+%if %{with_procevent}
+%files procevent
+%{_libdir}/%{name}/procevent.so
+%endif
+
 %if %{with_python}
 %files python
 %{_mandir}/man5/collectd-python*
@@ -2730,6 +2837,11 @@ fi
 %{_libdir}/%{name}/snmp_agent.so
 %endif
 
+%if %{with_sysevent}
+%files sysevent
+%{_libdir}/%{name}/sysevent.so
+%endif
+
 %if %{with_varnish}
 %files varnish
 %{_libdir}/%{name}/varnish.so
@@ -2760,6 +2872,16 @@ fi
 %{_libdir}/%{name}/write_riemann.so
 %endif
 
+%if %{with_write_stackdriver}
+%files write_stackdriver
+%{_libdir}/%{name}/write_stackdriver.so
+%endif
+
+%if %{with_gpu_nvidia}
+%files write_gpu_nvidia
+%{_libdir}/%{name}/write_gpu_nvidia.so
+%endif
+
 %if %{with_xencpu}
 %files xencpu
 %{_libdir}/%{name}/xencpu.so
@@ -2782,6 +2904,14 @@ fi
 %doc contrib/
 
 %changelog
+* Mon Oct 14 2019 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.9.2-2
+- Remove lvm plugin, liblvmapp has been deprecated upstream
+
+* Fri Jun 14 2019 Fabien Wernli <rpmbuild@faxmodem.org> - 5.9.0-1
+- add code for write_stackdriver (disabled for now)
+- add code for gpu_nvidia (disabled for now)
+- add pcie_errors
+
 * Thu Sep 28 2017 Jakub Jankowski <shasta@toxcorp.com> - 5.7.1-9
 - Fix mbmon/mcelog build options
 
index 089ff1d..e2f8ff1 100644 (file)
@@ -194,19 +194,25 @@ static int agg_instance_create_name(agg_instance_t *inst, /* {{{ */
       sstrncpy(tmp_plugin_instance, agg->ident.plugin_instance,
                sizeof(tmp_plugin_instance));
 
+    // Both tmp_plugin and tmp_plugin_instance are empty.
     if ((strcmp("", tmp_plugin) == 0) && (strcmp("", tmp_plugin_instance) == 0))
       sstrncpy(inst->ident.plugin_instance, AGG_FUNC_PLACEHOLDER,
                sizeof(inst->ident.plugin_instance));
-    else if (strcmp("", tmp_plugin) != 0)
-      snprintf(inst->ident.plugin_instance, sizeof(inst->ident.plugin_instance),
-               "%s-%s", tmp_plugin, AGG_FUNC_PLACEHOLDER);
-    else if (strcmp("", tmp_plugin_instance) != 0)
-      snprintf(inst->ident.plugin_instance, sizeof(inst->ident.plugin_instance),
-               "%s-%s", tmp_plugin_instance, AGG_FUNC_PLACEHOLDER);
+    // tmp_plugin is non-empty, and tmp_plugin_instance is empty.
+    else if (strcmp("", tmp_plugin_instance) == 0)
+      ssnprintf(inst->ident.plugin_instance,
+                sizeof(inst->ident.plugin_instance), "%s-%s", tmp_plugin,
+                AGG_FUNC_PLACEHOLDER);
+    // tmp_plugin is empty, and tmp_plugin_instance is non-empty.
+    else if (strcmp("", tmp_plugin) == 0)
+      ssnprintf(inst->ident.plugin_instance,
+                sizeof(inst->ident.plugin_instance), "%s-%s",
+                tmp_plugin_instance, AGG_FUNC_PLACEHOLDER);
+    // Both tmp_plugin and tmp_plugin_instance are non-empty.
     else
-      snprintf(inst->ident.plugin_instance, sizeof(inst->ident.plugin_instance),
-               "%s-%s-%s", tmp_plugin, tmp_plugin_instance,
-               AGG_FUNC_PLACEHOLDER);
+      ssnprintf(inst->ident.plugin_instance,
+                sizeof(inst->ident.plugin_instance), "%s-%s-%s", tmp_plugin,
+                tmp_plugin_instance, AGG_FUNC_PLACEHOLDER);
   }
 
   /* Type */
@@ -396,10 +402,9 @@ static int agg_instance_read(agg_instance_t *inst, cdtime_t t) /* {{{ */
     READ_FUNC(average, (inst->sum / ((gauge_t)inst->num)));
     READ_FUNC(min, inst->min);
     READ_FUNC(max, inst->max);
-    READ_FUNC(stddev,
-              sqrt((((gauge_t)inst->num) * inst->squares_sum) -
-                   (inst->sum * inst->sum)) /
-                  ((gauge_t)inst->num));
+    READ_FUNC(stddev, sqrt((((gauge_t)inst->num) * inst->squares_sum) -
+                           (inst->sum * inst->sum)) /
+                          ((gauge_t)inst->num));
   }
 
   /* Reset internal state. */
index 9eb5165..2077d57 100644 (file)
@@ -217,23 +217,23 @@ static char *camqp_strerror(camqp_config_t *conf, /* {{{ */
     if (r.reply.id == AMQP_CONNECTION_CLOSE_METHOD) {
       amqp_connection_close_t *m = r.reply.decoded;
       char *tmp = camqp_bytes_cstring(&m->reply_text);
-      snprintf(buffer, buffer_size, "Server connection error %d: %s",
-               m->reply_code, tmp);
+      ssnprintf(buffer, buffer_size, "Server connection error %d: %s",
+                m->reply_code, tmp);
       sfree(tmp);
     } else if (r.reply.id == AMQP_CHANNEL_CLOSE_METHOD) {
       amqp_channel_close_t *m = r.reply.decoded;
       char *tmp = camqp_bytes_cstring(&m->reply_text);
-      snprintf(buffer, buffer_size, "Server channel error %d: %s",
-               m->reply_code, tmp);
+      ssnprintf(buffer, buffer_size, "Server channel error %d: %s",
+                m->reply_code, tmp);
       sfree(tmp);
     } else {
-      snprintf(buffer, buffer_size, "Server error method %#" PRIx32,
-               r.reply.id);
+      ssnprintf(buffer, buffer_size, "Server error method %#" PRIx32,
+                r.reply.id);
     }
     break;
 
   default:
-    snprintf(buffer, buffer_size, "Unknown reply type %i", (int)r.reply_type);
+    ssnprintf(buffer, buffer_size, "Unknown reply type %i", (int)r.reply_type);
   }
 
   return buffer;
@@ -320,16 +320,17 @@ static int camqp_setup_queue(camqp_config_t *conf) /* {{{ */
   amqp_queue_declare_ok_t *qd_ret;
   amqp_basic_consume_ok_t *cm_ret;
 
-  qd_ret = amqp_queue_declare(conf->connection,
-                              /* channel     = */ CAMQP_CHANNEL,
-                              /* queue       = */ (conf->queue != NULL)
-                                  ? amqp_cstring_bytes(conf->queue)
-                                  : AMQP_EMPTY_BYTES,
-                              /* passive     = */ 0,
-                              /* durable     = */ conf->queue_durable,
-                              /* exclusive   = */ 0,
-                              /* auto_delete = */ conf->queue_auto_delete,
-                              /* arguments   = */ AMQP_EMPTY_TABLE);
+  qd_ret =
+      amqp_queue_declare(conf->connection,
+                         /* channel     = */ CAMQP_CHANNEL,
+                         /* queue       = */
+                         (conf->queue != NULL) ? amqp_cstring_bytes(conf->queue)
+                                               : AMQP_EMPTY_BYTES,
+                         /* passive     = */ 0,
+                         /* durable     = */ conf->queue_durable,
+                         /* exclusive   = */ 0,
+                         /* auto_delete = */ conf->queue_auto_delete,
+                         /* arguments   = */ AMQP_EMPTY_TABLE);
   if (qd_ret == NULL) {
     ERROR("amqp plugin: amqp_queue_declare failed.");
     camqp_close_connection(conf);
@@ -353,15 +354,15 @@ static int camqp_setup_queue(camqp_config_t *conf) /* {{{ */
     amqp_queue_bind_ok_t *qb_ret;
 
     assert(conf->queue != NULL);
-    qb_ret =
-        amqp_queue_bind(conf->connection,
-                        /* channel     = */ CAMQP_CHANNEL,
-                        /* queue       = */ amqp_cstring_bytes(conf->queue),
-                        /* exchange    = */ amqp_cstring_bytes(conf->exchange),
-                        /* routing_key = */ (conf->routing_key != NULL)
-                            ? amqp_cstring_bytes(conf->routing_key)
-                            : AMQP_EMPTY_BYTES,
-                        /* arguments   = */ AMQP_EMPTY_TABLE);
+    qb_ret = amqp_queue_bind(
+        conf->connection,
+        /* channel     = */ CAMQP_CHANNEL,
+        /* queue       = */ amqp_cstring_bytes(conf->queue),
+        /* exchange    = */ amqp_cstring_bytes(conf->exchange),
+        /* routing_key = */
+        (conf->routing_key != NULL) ? amqp_cstring_bytes(conf->routing_key)
+                                    : AMQP_EMPTY_BYTES,
+        /* arguments   = */ AMQP_EMPTY_TABLE);
     if ((qb_ret == NULL) && camqp_is_error(conf)) {
       char errbuf[1024];
       ERROR("amqp plugin: amqp_queue_bind failed: %s",
@@ -428,7 +429,7 @@ static int camqp_connect(camqp_config_t *conf) /* {{{ */
 
 #ifdef HAVE_AMQP_TCP_SOCKET
 #define CLOSE_SOCKET() /* amqp_destroy_connection() closes the socket for us   \
-                          */
+                        */
   /* TODO: add support for SSL using amqp_ssl_socket_new
    *       and related functions */
   socket = amqp_tcp_socket_new(conf->connection);
@@ -748,9 +749,9 @@ static int camqp_write(const data_set_t *ds, const value_list_t *vl, /* {{{ */
   if (conf->routing_key != NULL) {
     sstrncpy(routing_key, conf->routing_key, sizeof(routing_key));
   } else {
-    snprintf(routing_key, sizeof(routing_key), "collectd/%s/%s/%s/%s/%s",
-             vl->host, vl->plugin, vl->plugin_instance, vl->type,
-             vl->type_instance);
+    ssnprintf(routing_key, sizeof(routing_key), "collectd/%s/%s/%s/%s/%s",
+              vl->host, vl->plugin, vl->plugin_instance, vl->type,
+              vl->type_instance);
 
     /* Switch slashes (the only character forbidden by collectd) and dots
      * (the separation character used by AMQP). */
@@ -970,13 +971,13 @@ static int camqp_config_connection(oconfig_item_t *ci, /* {{{ */
 
   if (publish) {
     char cbname[128];
-    snprintf(cbname, sizeof(cbname), "amqp/%s", conf->name);
+    ssnprintf(cbname, sizeof(cbname), "amqp/%s", conf->name);
 
-    status =
-        plugin_register_write(cbname, camqp_write,
-                              &(user_data_t){
-                                  .data = conf, .free_func = camqp_config_free,
-                              });
+    status = plugin_register_write(cbname, camqp_write,
+                                   &(user_data_t){
+                                       .data = conf,
+                                       .free_func = camqp_config_free,
+                                   });
     if (status != 0) {
       camqp_config_free(conf);
       return status;
index a7fd26b..4325f00 100644 (file)
@@ -572,8 +572,10 @@ static int amqp1_config_instance(oconfig_item_t *ci) /* {{{ */
     else if (strcasecmp("Format", child->key) == 0) {
       char *key = NULL;
       status = cf_util_get_string(child, &key);
-      if (status != 0)
+      if (status != 0) {
+        amqp1_config_instance_free(instance);
         return status;
+      }
       assert(key != NULL);
       if (strcasecmp(key, "Command") == 0) {
         instance->format = AMQP1_FORMAT_COMMAND;
@@ -624,29 +626,33 @@ static int amqp1_config_instance(oconfig_item_t *ci) /* {{{ */
     return status;
   } else {
     char tpname[DATA_MAX_NAME_LEN];
-    status = snprintf(tpname, sizeof(tpname), "amqp1/%s", instance->name);
+    status = ssnprintf(tpname, sizeof(tpname), "amqp1/%s", instance->name);
     if ((status < 0) || (size_t)status >= sizeof(tpname)) {
       ERROR("amqp1 plugin: Instance name would have been truncated.");
+      amqp1_config_instance_free(instance);
       return -1;
     }
-    status = snprintf(instance->send_to, sizeof(instance->send_to), "/%s/%s",
-                      transport->address, instance->name);
+    status = ssnprintf(instance->send_to, sizeof(instance->send_to), "/%s/%s",
+                       transport->address, instance->name);
     if ((status < 0) || (size_t)status >= sizeof(instance->send_to)) {
       ERROR("amqp1 plugin: send_to address would have been truncated.");
+      amqp1_config_instance_free(instance);
       return -1;
     }
     if (instance->notify) {
       status = plugin_register_notification(
           tpname, amqp1_notify,
           &(user_data_t){
-              .data = instance, .free_func = amqp1_config_instance_free,
+              .data = instance,
+              .free_func = amqp1_config_instance_free,
           });
     } else {
-      status = plugin_register_write(
-          tpname, amqp1_write,
-          &(user_data_t){
-              .data = instance, .free_func = amqp1_config_instance_free,
-          });
+      status =
+          plugin_register_write(tpname, amqp1_write,
+                                &(user_data_t){
+                                    .data = instance,
+                                    .free_func = amqp1_config_instance_free,
+                                });
     }
 
     if (status != 0) {
index d64e547..4014bba 100644 (file)
@@ -224,7 +224,8 @@ static int config_add(oconfig_item_t *ci) {
       /* callback  = */ apache_read_host,
       /* interval  = */ 0,
       &(user_data_t){
-          .data = st, .free_func = apache_free,
+          .data = st,
+          .free_func = apache_free,
       });
 } /* int config_add */
 
index dfa2804..61dd76d 100644 (file)
@@ -81,8 +81,8 @@ static void aquaero_submit_array(const char *type,
     if (value_array[i] == AQ5_FLOAT_UNDEF)
       continue;
 
-    snprintf(type_instance, sizeof(type_instance), "%s%d", type_instance_prefix,
-             i + 1);
+    ssnprintf(type_instance, sizeof(type_instance), "%s%d",
+              type_instance_prefix, i + 1);
     aquaero_submit(type, type_instance, value_array[i]);
   }
 }
@@ -130,7 +130,7 @@ static int aquaero_read(void) {
         (aq_data.fan_vrm_temp[i] != AQ5_FLOAT_UNDEF))
       continue;
 
-    snprintf(type_instance, sizeof(type_instance), "fan%d", i + 1);
+    ssnprintf(type_instance, sizeof(type_instance), "fan%d", i + 1);
 
     aquaero_submit("fanspeed", type_instance, aq_data.fan_rpm[i]);
     aquaero_submit("percent", type_instance, aq_data.fan_duty[i]);
@@ -139,7 +139,7 @@ static int aquaero_read(void) {
 
     /* Report the voltage reglator module (VRM) temperature with a
      * different type instance. */
-    snprintf(type_instance, sizeof(type_instance), "fan%d-vrm", i + 1);
+    ssnprintf(type_instance, sizeof(type_instance), "fan%d-vrm", i + 1);
     aquaero_submit("temperature", type_instance, aq_data.fan_vrm_temp[i]);
   }
 
index e5589bf..6240e31 100644 (file)
@@ -499,8 +499,8 @@ static int ascent_init(void) /* {{{ */
     static char credentials[1024];
     int status;
 
-    status = snprintf(credentials, sizeof(credentials), "%s:%s", user,
-                      (pass == NULL) ? "" : pass);
+    status = ssnprintf(credentials, sizeof(credentials), "%s:%s", user,
+                       (pass == NULL) ? "" : pass);
     if ((status < 0) || ((size_t)status >= sizeof(credentials))) {
       ERROR("ascent plugin: ascent_init: Returning an error because the "
             "credentials have been truncated.");
index 468a237..fd733b4 100644 (file)
@@ -1309,8 +1309,8 @@ static int collectd_barometer_config(const char *key, const char *value) {
   } else if (strcasecmp(key, "Normalization") == 0) {
     int normalize_tmp = atoi(value);
     if (normalize_tmp < 0 || normalize_tmp > 2) {
-      WARNING("barometer: collectd_barometer_config: invalid normalization: %d",
-              normalize_tmp);
+      ERROR("barometer: collectd_barometer_config: invalid normalization: %d",
+            normalize_tmp);
       return 1;
     }
     config_normalize = normalize_tmp;
index 8e6c4b2..9b5b82d 100644 (file)
@@ -336,7 +336,7 @@ static int battery_read(void) /* {{{ */
 
   return 0;
 } /* }}} int battery_read */
-/* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
+  /* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
 
 #elif KERNEL_LINUX
 /* Reads a file which contains only a number (and optionally a trailing
@@ -349,12 +349,10 @@ static int sysfs_file_to_buffer(char const *dir, /* {{{ */
 
   snprintf(filename, sizeof(filename), "%s/%s/%s", dir, power_supply, basename);
 
-  status = (int)read_file_contents(filename, buffer, buffer_size - 1);
+  status = (int)read_text_file_contents(filename, buffer, buffer_size);
   if (status < 0)
     return status;
 
-  buffer[status] = '\0';
-
   strstripnewline(buffer);
   return 0;
 } /* }}} int sysfs_file_to_buffer */
index 29f65d4..a246f1a 100644 (file)
@@ -1538,8 +1538,9 @@ static int bind_init(void) /* {{{ */
   curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
 #ifdef HAVE_CURLOPT_TIMEOUT_MS
   curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS,
-                   (timeout >= 0) ? (long)timeout : (long)CDTIME_T_TO_MS(
-                                                        plugin_get_interval()));
+                   (timeout >= 0)
+                       ? (long)timeout
+                       : (long)CDTIME_T_TO_MS(plugin_get_interval()));
 #endif
 
   return 0;
index 19a09d8..8048f5d 100644 (file)
@@ -990,7 +990,7 @@ static int cconn_connect(struct cconn *io) {
     return err;
   }
   address.sun_family = AF_UNIX;
-  snprintf(address.sun_path, sizeof(address.sun_path), "%s", io->d->asok_path);
+  ssnprintf(address.sun_path, sizeof(address.sun_path), "%s", io->d->asok_path);
   RETRY_ON_EINTR(err, connect(fd, (struct sockaddr *)&address,
                               sizeof(struct sockaddr_un)));
   if (err < 0) {
@@ -1153,8 +1153,8 @@ static ssize_t cconn_handle_event(struct cconn *io) {
     return -EDOM;
   case CSTATE_WRITE_REQUEST: {
     char cmd[32];
-    snprintf(cmd, sizeof(cmd), "%s%d%s", "{ \"prefix\": \"", io->request_type,
-             "\" }\n");
+    ssnprintf(cmd, sizeof(cmd), "%s%d%s", "{ \"prefix\": \"", io->request_type,
+              "\" }\n");
     size_t cmd_len = strlen(cmd);
     RETRY_ON_EINTR(
         ret, write(io->asok, ((char *)&cmd) + io->amt, cmd_len - io->amt));
diff --git a/src/check_uptime.c b/src/check_uptime.c
new file mode 100644 (file)
index 0000000..33363b5
--- /dev/null
@@ -0,0 +1,273 @@
+/**
+ * collectd - src/check_uptime.c
+ * Copyright (C) 2007-2019  Florian Forster
+ * Copyright (C) 2019  Pavel V. Rochnyack
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Author:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Pavel Rochnyak <pavel2000 ngs.ru>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "utils/avltree/avltree.h"
+#include "utils/common/common.h"
+#include "utils_cache.h"
+
+/* Types are registered only in `config` phase, so access is not protected by
+ * locks */
+c_avl_tree_t *types_tree = NULL;
+
+static int format_uptime(unsigned long uptime_sec, char *buf, size_t bufsize) {
+
+  unsigned int uptime_days = uptime_sec / 24 / 3600;
+  uptime_sec -= uptime_days * 24 * 3600;
+  unsigned int uptime_hours = uptime_sec / 3600;
+  uptime_sec -= uptime_hours * 3600;
+  unsigned int uptime_mins = uptime_sec / 60;
+  uptime_sec -= uptime_mins * 60;
+
+  int ret = 0;
+  if (uptime_days) {
+    ret += snprintf(buf + ret, bufsize - ret, " %u day(s)", uptime_days);
+  }
+  if (uptime_days || uptime_hours) {
+    ret += snprintf(buf + ret, bufsize - ret, " %u hour(s)", uptime_hours);
+  }
+  if (uptime_days || uptime_hours || uptime_mins) {
+    ret += snprintf(buf + ret, bufsize - ret, " %u min", uptime_mins);
+  }
+  ret += snprintf(buf + ret, bufsize - ret, " %lu sec.", uptime_sec);
+  return ret;
+}
+
+static int cu_notify(enum cache_event_type_e event_type, const value_list_t *vl,
+                     gauge_t old_uptime, gauge_t new_uptime) {
+  notification_t n;
+  NOTIFICATION_INIT_VL(&n, vl);
+
+  int status;
+  char *buf = n.message;
+  size_t bufsize = sizeof(n.message);
+
+  n.time = vl->time;
+
+  const char *service = "Service";
+  if (strcmp(vl->plugin, "uptime") == 0)
+    service = "Host";
+
+  switch (event_type) {
+  case CE_VALUE_NEW:
+    n.severity = NOTIF_OKAY;
+    status = snprintf(buf, bufsize, "%s is running.", service);
+    buf += status;
+    bufsize -= status;
+    break;
+  case CE_VALUE_UPDATE:
+    n.severity = NOTIF_WARNING;
+    status = snprintf(buf, bufsize, "%s just restarted.", service);
+    buf += status;
+    bufsize -= status;
+    break;
+  case CE_VALUE_EXPIRED:
+    n.severity = NOTIF_FAILURE;
+    status = snprintf(buf, bufsize, "%s is unreachable.", service);
+    buf += status;
+    bufsize -= status;
+    break;
+  }
+
+  if (!isnan(old_uptime)) {
+    status = snprintf(buf, bufsize, " Uptime was:");
+    buf += status;
+    bufsize -= status;
+
+    status = format_uptime(old_uptime, buf, bufsize);
+    buf += status;
+    bufsize -= status;
+
+    plugin_notification_meta_add_double(&n, "LastValue", old_uptime);
+  }
+
+  if (!isnan(new_uptime)) {
+    status = snprintf(buf, bufsize, " Uptime now:");
+    buf += status;
+    bufsize -= status;
+
+    status = format_uptime(new_uptime, buf, bufsize);
+    buf += status;
+    bufsize -= status;
+
+    plugin_notification_meta_add_double(&n, "CurrentValue", new_uptime);
+  }
+
+  plugin_dispatch_notification(&n);
+
+  plugin_notification_meta_free(n.meta);
+  return 0;
+}
+
+static int cu_cache_event(cache_event_t *event,
+                          __attribute__((unused)) user_data_t *ud) {
+  gauge_t values_history[2];
+
+  /* For CE_VALUE_EXPIRED */
+  int ret;
+  value_t *values;
+  size_t values_num;
+  gauge_t old_uptime = NAN;
+
+  switch (event->type) {
+  case CE_VALUE_NEW:
+    DEBUG("check_uptime: CE_VALUE_NEW, %s", event->value_list_name);
+    if (c_avl_get(types_tree, event->value_list->type, NULL) == 0) {
+      event->ret = 1;
+      assert(event->value_list->values_len > 0);
+      cu_notify(CE_VALUE_NEW, event->value_list, NAN /* old */,
+                event->value_list->values[0].gauge /* new */);
+    }
+    break;
+  case CE_VALUE_UPDATE:
+    DEBUG("check_uptime: CE_VALUE_UPDATE, %s", event->value_list_name);
+    if (uc_get_history_by_name(event->value_list_name, values_history, 2, 1)) {
+      ERROR("check_uptime plugin: Failed to get value history for %s.",
+            event->value_list_name);
+    } else {
+      if (!isnan(values_history[0]) && !isnan(values_history[1]) &&
+          values_history[0] < values_history[1]) {
+        cu_notify(CE_VALUE_UPDATE, event->value_list,
+                  values_history[1] /* old */, values_history[0] /* new */);
+      }
+    }
+    break;
+  case CE_VALUE_EXPIRED:
+    DEBUG("check_uptime: CE_VALUE_EXPIRED, %s", event->value_list_name);
+    ret = uc_get_value_by_name(event->value_list_name, &values, &values_num);
+    if (ret == 0) {
+      old_uptime = values[0].gauge;
+      sfree(values);
+    }
+
+    cu_notify(CE_VALUE_EXPIRED, event->value_list, old_uptime, NAN /* new */);
+    break;
+  }
+  return 0;
+}
+
+static int cu_config(oconfig_item_t *ci) {
+  if (types_tree == NULL) {
+    types_tree = c_avl_create((int (*)(const void *, const void *))strcmp);
+    if (types_tree == NULL) {
+      ERROR("check_uptime plugin: c_avl_create failed.");
+      return -1;
+    }
+  }
+
+  for (int i = 0; i < ci->children_num; ++i) {
+    oconfig_item_t *child = ci->children + i;
+    if (strcasecmp("Type", child->key) == 0) {
+      if ((child->values_num != 1) ||
+          (child->values[0].type != OCONFIG_TYPE_STRING)) {
+        WARNING("check_uptime plugin: The `Type' option needs exactly one "
+                "string argument.");
+        return -1;
+      }
+      char *type = child->values[0].value.string;
+
+      if (c_avl_get(types_tree, type, NULL) == 0) {
+        ERROR("check_uptime plugin: Type `%s' already added.", type);
+        return -1;
+      }
+
+      char *type_copy = strdup(type);
+      if (type_copy == NULL) {
+        ERROR("check_uptime plugin: strdup failed.");
+        return -1;
+      }
+
+      int status = c_avl_insert(types_tree, type_copy, NULL);
+      if (status != 0) {
+        ERROR("check_uptime plugin: c_avl_insert failed.");
+        sfree(type_copy);
+        return -1;
+      }
+    } else
+      WARNING("check_uptime plugin: Ignore unknown config option `%s'.",
+              child->key);
+  }
+
+  return 0;
+}
+
+static int cu_init(void) {
+  if (types_tree == NULL) {
+    types_tree = c_avl_create((int (*)(const void *, const void *))strcmp);
+    if (types_tree == NULL) {
+      ERROR("check_uptime plugin: c_avl_create failed.");
+      return -1;
+    }
+    /* Default configuration */
+    char *type = strdup("uptime");
+    if (type == NULL) {
+      ERROR("check_uptime plugin: strdup failed.");
+      return -1;
+    }
+    int status = c_avl_insert(types_tree, type, NULL);
+    if (status != 0) {
+      ERROR("check_uptime plugin: c_avl_insert failed.");
+      sfree(type);
+      return -1;
+    }
+  }
+
+  int ret = 0;
+  char *type;
+  void *val;
+  c_avl_iterator_t *iter = c_avl_get_iterator(types_tree);
+  while (c_avl_iterator_next(iter, (void *)&type, (void *)&val) == 0) {
+    data_set_t const *ds = plugin_get_ds(type);
+    if (ds == NULL) {
+      ERROR("check_uptime plugin: Failed to look up type \"%s\".", type);
+      ret = -1;
+      continue;
+    }
+    if (ds->ds_num != 1) {
+      ERROR("check_uptime plugin: The type \"%s\" has %" PRIsz " data sources. "
+            "Only types with a single GAUGE data source are supported.",
+            ds->type, ds->ds_num);
+      ret = -1;
+      continue;
+    }
+    if (ds->ds[0].type != DS_TYPE_GAUGE) {
+      ERROR("check_uptime plugin: The type \"%s\" has wrong data source type. "
+            "Only types with a single GAUGE data source are supported.",
+            ds->type);
+      ret = -1;
+      continue;
+    }
+  }
+  c_avl_iterator_destroy(iter);
+
+  if (ret == 0)
+    plugin_register_cache_event("check_uptime", cu_cache_event, NULL);
+
+  return ret;
+}
+
+void module_register(void) {
+  plugin_register_complex_config("check_uptime", cu_config);
+  plugin_register_init("check_uptime", cu_init);
+}
index 65e3c4c..079a335 100644 (file)
@@ -111,7 +111,9 @@ typedef enum {
 #define ATTRIB_PACKED
 #endif
 
-typedef struct ATTRIB_PACKED { int32_t value; } tFloat;
+typedef struct ATTRIB_PACKED {
+  int32_t value;
+} tFloat;
 
 typedef struct ATTRIB_PACKED {
   uint32_t tv_sec_high;
@@ -148,7 +150,9 @@ typedef struct ATTRIB_PACKED {
                            Amplification) */
 } tChrony_Req_Tracking;
 
-typedef struct ATTRIB_PACKED { uint32_t f_n_sources; } tChrony_Req_N_Sources;
+typedef struct ATTRIB_PACKED {
+  uint32_t f_n_sources;
+} tChrony_Req_N_Sources;
 
 typedef struct ATTRIB_PACKED {
   int32_t f_index;
@@ -183,7 +187,9 @@ typedef struct ATTRIB_PACKED {
 } tChrony_Request;
 
 /* Chrony daemon response packets */
-typedef struct ATTRIB_PACKED { uint32_t f_n_sources; } tChrony_Resp_N_Sources;
+typedef struct ATTRIB_PACKED {
+  uint32_t f_n_sources;
+} tChrony_Resp_N_Sources;
 
 typedef struct ATTRIB_PACKED {
   union {
index 493f5ec..5e99ba3 100644 (file)
@@ -373,6 +373,10 @@ How long to wait for a response. The C<Net-SNMP> library default is 1 second.
 The number of times that a query should be retried after the Timeout expires.
 The C<Net-SNMP> library default is 5.
 
+=item B<BulkSize> I<Integer>
+
+Configures the size of SNMP bulk transfers. The default is 0, which disables bulk transfers altogether.
+
 =back
 
 =head1 SEE ALSO
index f09f373..63db8b1 100644 (file)
 #@BUILD_PLUGIN_CEPH_TRUE@LoadPlugin ceph
 #@BUILD_PLUGIN_CGROUPS_TRUE@LoadPlugin cgroups
 #@BUILD_PLUGIN_CHRONY_TRUE@LoadPlugin chrony
+#@BUILD_PLUGIN_CHECK_UPTIME_TRUE@LoadPlugin check_uptime
+#@BUILD_PLUGIN_CONNECTIVITY_TRUE@LoadPlugin connectivity
 #@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
 #@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@LoadPlugin contextswitch
 @BUILD_PLUGIN_CPU_TRUE@@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
 @BUILD_PLUGIN_LOAD_TRUE@@BUILD_PLUGIN_LOAD_TRUE@LoadPlugin load
 #@BUILD_PLUGIN_LPAR_TRUE@LoadPlugin lpar
 #@BUILD_PLUGIN_LUA_TRUE@LoadPlugin lua
-#@BUILD_PLUGIN_LVM_TRUE@LoadPlugin lvm
 #@BUILD_PLUGIN_MADWIFI_TRUE@LoadPlugin madwifi
 #@BUILD_PLUGIN_MBMON_TRUE@LoadPlugin mbmon
 #@BUILD_PLUGIN_MCELOG_TRUE@LoadPlugin mcelog
 #@BUILD_PLUGIN_POSTGRESQL_TRUE@LoadPlugin postgresql
 #@BUILD_PLUGIN_POWERDNS_TRUE@LoadPlugin powerdns
 #@BUILD_PLUGIN_PROCESSES_TRUE@LoadPlugin processes
+#@BUILD_PLUGIN_PROCEVENT_TRUE@LoadPlugin procevent
 #@BUILD_PLUGIN_PROTOCOLS_TRUE@LoadPlugin protocols
 #@BUILD_PLUGIN_PYTHON_TRUE@LoadPlugin python
 #@BUILD_PLUGIN_REDIS_TRUE@LoadPlugin redis
 #@BUILD_PLUGIN_SNMP_AGENT_TRUE@LoadPlugin snmp_agent
 #@BUILD_PLUGIN_STATSD_TRUE@LoadPlugin statsd
 #@BUILD_PLUGIN_SWAP_TRUE@LoadPlugin swap
+#@BUILD_PLUGIN_SYSEVENT_TRUE@LoadPlugin sysevent
 #@BUILD_PLUGIN_TABLE_TRUE@LoadPlugin table
 #@BUILD_PLUGIN_TAIL_TRUE@LoadPlugin tail
 #@BUILD_PLUGIN_TAIL_CSV_TRUE@LoadPlugin tail_csv
 #      Timeout "2"
 #</Plugin>
 
+#<Plugin connectivity>
+#  Interface eth0
+#</Plugin>
+
 #<Plugin cgroups>
 #  CGroup "libvirt"
 #  IgnoreSelected false
 #      </Process>
 #</Plugin>
 
+#<Plugin "procevent">
+#  BufferLength 10
+#  ProcessRegex "/^ovs.*$/" 
+#  Process tuned
+#</Plugin>
+
 #<Plugin protocols>
 #      Value "/^Tcp:/"
 #      IgnoreSelected false
 #       Version 2
 #       Community "another_string"
 #       Collect "std_traffic" "hr_users"
+#       BulkSize 0
 #   </Host>
 #   <Host "some.ups.mydomain.org">
 #       Address "192.168.0.3"
 #      Timeout 5
 #      Retries 5
 #   </Host>
+#   <Host "highend.switch.example.org">
+#       Address "192.168.0.3"
+#       Version 2
+#       Community "another_string"
+#       Collect "std_traffic"
+#       Interval 10
+#       Timeout 10
+#       BulkSize 100
+#   </Host>
 #</Plugin>
 
 #<Plugin snmp_agent>
 #      ReportIO true
 #</Plugin>
 
+#<Plugin sysevent>
+#       Listen "127.0.0.1" "6666"
+#       BufferSize 1024
+#       BufferLength 10
+#       RegexFilter "regex"
+#</Plugin>
+
 #<Plugin table>
 #      <Table "/proc/slabinfo">
 #              #Plugin "table"
index ed49195..cda1002 100644 (file)
@@ -1548,6 +1548,35 @@ at all, B<all> cgroups are selected.
 
 =back
 
+=head2 Plugin C<check_uptime>
+
+The I<check_uptime plugin> designed to check and notify about host or service
+status based on I<uptime> metric.
+
+When new metric of I<uptime> type appears in cache, OK notification is sent.
+When new value for metric is less than previous value, WARNING notification is
+sent about host/service restart.
+When no new updates comes for metric and cache entry expires, then FAILURE
+notification is sent about unreachable host or service.
+
+By default (when no explicit configuration), plugin checks for I<uptime> metric.
+
+B<Synopsis:>
+
+ <Plugin "check_uptime">
+   Type "uptime"
+   Type "my_uptime_type"
+ </Plugin>
+
+=over 4
+
+=item B<Type> I<Type>
+
+Metric type to check for status/values. The type should consist single GAUGE
+data source.
+
+=back
+
 =head2 Plugin C<chrony>
 
 The C<chrony> plugin collects ntp data from a B<chronyd> server, such as clock
@@ -1574,6 +1603,47 @@ Connection timeout in seconds. Defaults to B<2>.
 
 =back
 
+=head2 Plugin Connectivity
+
+connectivity - Documentation of collectd's C<connectivity plugin>
+
+
+  LoadPlugin connectivity
+  # ...
+  <Plugin connectivity>
+    Interface eth0
+  </Plugin>
+
+The C<connectivity plugin> queries interface status using netlink (man 7 netlink) which provides information about network interfaces via the NETLINK_ROUTE family (man 7 rtnetlink). The plugin translates the value it receives to collectd's internal format and, depending on the write plugins you have loaded, it may be written to disk or submitted to another instance.
+The plugin listens to interfaces enumerated within the plugin configuration (see below).  If no interfaces are listed, then the default is for all interfaces to be monitored.
+
+This example shows C<connectivity plugin> monitoring all interfaces.
+LoadPlugin connectivity
+<Plugin connectivity>
+</Plugin>
+
+This example shows C<connectivity plugin> monitoring 2 interfaces, "eth0" and "eth1".
+LoadPlugin connectivity
+<Plugin connectivity>
+  Interface eth0
+  Interface eth1
+</Plugin>
+
+This example shows C<connectivity plugin> monitoring all interfaces except "eth1".
+LoadPlugin connectivity
+<Plugin connectivity>
+  Interface eth1
+  IgnoreSelected true
+</Plugin>
+=over 4
+
+=item B<Interface> I<interface_name>
+
+interface(s) to monitor connect to. 
+
+=back
+
 =head2 Plugin C<conntrack>
 
 This plugin collects IP conntrack statistics.
@@ -4758,7 +4828,7 @@ Hostname of the database server. Defaults to B<localhost>.
 
 Username to use when connecting to the database. The user does not have to be
 granted any privileges (which is synonym to granting the C<USAGE> privilege),
-unless you want to collectd replication statistics (see B<MasterStats> and
+unless you want to collect replication statistics (see B<MasterStats> and
 B<SlaveStats> below). In this case, the user needs the C<REPLICATION CLIENT>
 (or C<SUPER>) privileges. Else, any existing MySQL user will do.
 
@@ -4808,9 +4878,10 @@ or SQL threads are not running. Defaults to B<false>.
 
 =item B<WsrepStats> I<true|false>
 
- Enable the collection of wsrep plugin statistics, used in Master-Master
- replication setups like in MySQL Galera/Percona XtraDB Cluster.
- User needs only privileges to execute 'SHOW GLOBAL STATUS'
+Enable the collection of wsrep plugin statistics, used in Master-Master
+replication setups like in MySQL Galera/Percona XtraDB Cluster.
+User needs only privileges to execute 'SHOW GLOBAL STATUS'.
+Defaults to B<false>.
 
 =item B<ConnectTimeout> I<Seconds>
 
@@ -7314,6 +7385,40 @@ reporting the corresponding processes only. Outside of B<Process> and
 B<ProcessMatch> blocks these options set the default value for subsequent
 matches.
 
+=head2 Plugin C<procevent>
+The I<procevent> plugin monitors when processes start (EXEC) and stop (EXIT).
+B<Synopsis:>
+  <Plugin procevent>
+    BufferLength 10
+    Process "name"
+    ProcessRegex "regex"
+  </Plugin>
+B<Options:>
+=over 4
+=item B<BufferLength> I<length>
+Maximum number of process events that can be stored in plugin's ring buffer.
+By default, this is set to 10.  Once an event has been read, its location
+becomes available for storing a new event.
+=item B<Process> I<name>
+Enumerate a process name to monitor.  All processes that match this exact
+name will be monitored for EXECs and EXITs.
+
+=item B<ProcessRegex> I<regex>
+Enumerate a process pattern to monitor.  All processes that match this 
+regular expression will be monitored for EXECs and EXITs.
+=back
+
 =head2 Plugin C<protocols>
 
 Collects a lot of information about various network protocols, such as I<IP>,
@@ -8247,6 +8352,70 @@ or is not reliable.
 
 =back
 
+=head2 Plugin C<sysevent>
+The I<sysevent> plugin monitors rsyslog messages.
+B<Synopsis:>
+  <Plugin sysevent>
+    Listen "192.168.0.2" "6666"
+    BufferSize 1024
+    BufferLength 10
+    RegexFilter "regex"
+  </Plugin>
+
+  rsyslog should be configured such that it sends data to the IP and port you
+  include in the plugin configuration.  For example, given the configuration
+  above, something like this would be set in /etc/rsyslog.conf:
+
+    if $programname != 'collectd' then
+    *.* @192.168.0.2:6666
+
+  This plugin is designed to consume JSON rsyslog data, so a more complete
+  rsyslog configuration would look like so (where we define a JSON template
+  and use it when sending data to our IP and port):
+
+    $template ls_json,"{%timestamp:::date-rfc3339,jsonf:@timestamp%, \
+    %source:::jsonf:@source_host%,\"@source\":\"syslog://%fromhost-ip:::json%\", \
+    \"@message\":\"%timestamp% %app-name%:%msg:::json%\",\"@fields\": \
+    {%syslogfacility-text:::jsonf:facility%,%syslogseverity:::jsonf:severity-num%, \
+    %syslogseverity-text:::jsonf:severity%,%programname:::jsonf:program%, \
+    %procid:::jsonf:processid%}}"
+
+    if $programname != 'collectd' then
+    *.* @192.168.0.2:6666;ls_json
+
+  Please note that these rsyslog.conf examples are *not* complete, as rsyslog
+  requires more than these options in the configuration file.  These examples 
+  are meant to demonstration the proper remote logging and JSON format syntax.
+
+B<Options:>
+=over 4
+=item B<Listen> I<host> I<port>
+Listen on this IP on this port for incoming rsyslog messages.
+
+=item B<BufferSize> I<length>
+Maximum allowed size for incoming rsyslog messages.  Messages that exceed 
+this number will be truncated to this size.  Default is 4096 bytes.
+
+=item B<BufferLength> I<length>
+Maximum number of rsyslog events that can be stored in plugin's ring buffer.
+By default, this is set to 10.  Once an event has been read, its location
+becomes available for storing a new event.
+
+=item B<RegexFilter> I<regex>
+Enumerate a regex filter to apply to all incoming rsyslog messages.  If a
+message matches this filter, it will be published.
+=back
+
 =head2 Plugin C<syslog>
 
 =over 4
index 54c8081..3974fd0 100644 (file)
@@ -25,6 +25,7 @@
 #include "config.h"
 #endif
 
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 extern char *optarg;
 extern int optind;
 
+/* _ssnprintf returns result from vsnprintf (consistent with snprintf) */
+static int _ssnprintf(char *str, size_t sz, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+
+  int ret = vsnprintf(str, sz, format, ap);
+
+  va_end(ap);
+
+  return ret;
+} /* int _ssnprintf */
+
 __attribute__((noreturn)) static void exit_usage(const char *name, int status) {
   fprintf(
       (status == 0) ? stdout : stderr,
@@ -166,7 +179,7 @@ static int parse_identifier(lcc_connection_t *c, const char *value,
     }
     hostname[sizeof(hostname) - 1] = '\0';
 
-    snprintf(ident_str, sizeof(ident_str), "%s/%s", hostname, value);
+    _ssnprintf(ident_str, sizeof(ident_str), "%s/%s", hostname, value);
     ident_str[sizeof(ident_str) - 1] = '\0';
   } else {
     strncpy(ident_str, value, sizeof(ident_str));
@@ -276,8 +289,9 @@ static int flush(lcc_connection_t *c, int argc, char **argv) {
                 value);
         BAIL_OUT(-1);
       } else if ((endptr != NULL) && (*endptr != '\0')) {
-        fprintf(stderr, "WARNING: Ignoring trailing garbage after timeout: "
-                        "%s.\n",
+        fprintf(stderr,
+                "WARNING: Ignoring trailing garbage after timeout: "
+                "%s.\n",
                 endptr);
       }
     } else if (strcasecmp(key, "plugin") == 0) {
@@ -324,8 +338,9 @@ static int flush(lcc_connection_t *c, int argc, char **argv) {
           char id[1024];
 
           lcc_identifier_to_string(c, id, sizeof(id), identifiers + j);
-          fprintf(stderr, "ERROR: Failed to flush plugin `%s', "
-                          "identifier `%s': %s.\n",
+          fprintf(stderr,
+                  "ERROR: Failed to flush plugin `%s', "
+                  "identifier `%s': %s.\n",
                   (plugins[i] == NULL) ? "(all)" : plugins[i], id,
                   lcc_strerror(c));
         }
@@ -369,8 +384,9 @@ static int listval(lcc_connection_t *c, int argc, char **argv) {
 
     status = lcc_identifier_to_string(c, id, sizeof(id), ret_ident + i);
     if (status != 0) {
-      fprintf(stderr, "ERROR: listval: Failed to convert returned "
-                      "identifier to a string: %s\n",
+      fprintf(stderr,
+              "ERROR: listval: Failed to convert returned "
+              "identifier to a string: %s\n",
               lcc_strerror(c));
       continue;
     }
@@ -428,8 +444,9 @@ static int putval(lcc_connection_t *c, int argc, char **argv) {
                   value);
           return -1;
         } else if ((endptr != NULL) && (*endptr != '\0')) {
-          fprintf(stderr, "WARNING: Ignoring trailing garbage after "
-                          "interval: %s.\n",
+          fprintf(stderr,
+                  "WARNING: Ignoring trailing garbage after "
+                  "interval: %s.\n",
                   endptr);
         }
       } else {
@@ -543,7 +560,7 @@ int main(int argc, char **argv) {
 
     switch (opt) {
     case 's':
-      snprintf(address, sizeof(address), "unix:%s", optarg);
+      _ssnprintf(address, sizeof(address), "unix:%s", optarg);
       address[sizeof(address) - 1] = '\0';
       break;
     case 'h':
index 0e2b021..6affd3c 100644 (file)
@@ -255,8 +255,9 @@ static void check_respawn(void) {
   if (counter >= 10) {
     unsigned int time_left = 300;
 
-    syslog(LOG_ERR, "Error: collectd is respawning too fast - "
-                    "disabled for %i seconds",
+    syslog(LOG_ERR,
+           "Error: collectd is respawning too fast - "
+           "disabled for %i seconds",
            time_left);
 
     while (((time_left = sleep(time_left)) > 0) && loop == 0)
@@ -323,7 +324,8 @@ int main(int argc, char **argv) {
   }
 
   struct sigaction sa = {
-      .sa_handler = sig_int_term_handler, .sa_flags = 0,
+      .sa_handler = sig_int_term_handler,
+      .sa_flags = 0,
   };
   sigemptyset(&sa.sa_mask);
 
diff --git a/src/connectivity.c b/src/connectivity.c
new file mode 100644 (file)
index 0000000..45b65aa
--- /dev/null
@@ -0,0 +1,1032 @@
+/**
+ * collectd - src/connectivity.c
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Red Hat NFVPE
+ *     Andrew Bays <abays at redhat.com>
+ *     Aneesh Puttur <aputtur at redhat.com>
+ **/
+
+#include "collectd.h"
+
+#include "plugin.h"
+#include "utils/common/common.h"
+#include "utils/ignorelist/ignorelist.h"
+#include "utils_complain.h"
+
+#include <asm/types.h>
+#include <errno.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <libmnl/libmnl.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <yajl/yajl_common.h>
+#include <yajl/yajl_gen.h>
+#if HAVE_YAJL_YAJL_VERSION_H
+#include <yajl/yajl_version.h>
+#endif
+#if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1)
+#define HAVE_YAJL_V2 1
+#endif
+
+#define MYPROTO NETLINK_ROUTE
+
+#define LINK_STATE_DOWN 0
+#define LINK_STATE_UP 1
+#define LINK_STATE_UNKNOWN 2
+
+#define CONNECTIVITY_DOMAIN_FIELD "domain"
+#define CONNECTIVITY_DOMAIN_VALUE "stateChange"
+#define CONNECTIVITY_EVENT_ID_FIELD "eventId"
+#define CONNECTIVITY_EVENT_NAME_FIELD "eventName"
+#define CONNECTIVITY_EVENT_NAME_DOWN_VALUE "down"
+#define CONNECTIVITY_EVENT_NAME_UP_VALUE "up"
+#define CONNECTIVITY_LAST_EPOCH_MICROSEC_FIELD "lastEpochMicrosec"
+#define CONNECTIVITY_PRIORITY_FIELD "priority"
+#define CONNECTIVITY_PRIORITY_VALUE "high"
+#define CONNECTIVITY_REPORTING_ENTITY_NAME_FIELD "reportingEntityName"
+#define CONNECTIVITY_REPORTING_ENTITY_NAME_VALUE "collectd connectivity plugin"
+#define CONNECTIVITY_SEQUENCE_FIELD "sequence"
+#define CONNECTIVITY_SEQUENCE_VALUE "0"
+#define CONNECTIVITY_SOURCE_NAME_FIELD "sourceName"
+#define CONNECTIVITY_START_EPOCH_MICROSEC_FIELD "startEpochMicrosec"
+#define CONNECTIVITY_VERSION_FIELD "version"
+#define CONNECTIVITY_VERSION_VALUE "1.0"
+
+#define CONNECTIVITY_NEW_STATE_FIELD "newState"
+#define CONNECTIVITY_NEW_STATE_FIELD_DOWN_VALUE "outOfService"
+#define CONNECTIVITY_NEW_STATE_FIELD_UP_VALUE "inService"
+#define CONNECTIVITY_OLD_STATE_FIELD "oldState"
+#define CONNECTIVITY_OLD_STATE_FIELD_DOWN_VALUE "outOfService"
+#define CONNECTIVITY_OLD_STATE_FIELD_UP_VALUE "inService"
+#define CONNECTIVITY_STATE_CHANGE_FIELDS_FIELD "stateChangeFields"
+#define CONNECTIVITY_STATE_CHANGE_FIELDS_VERSION_FIELD                         \
+  "stateChangeFieldsVersion"
+#define CONNECTIVITY_STATE_CHANGE_FIELDS_VERSION_VALUE "1.0"
+#define CONNECTIVITY_STATE_INTERFACE_FIELD "stateInterface"
+
+/*
+ * Private data types
+ */
+
+struct interface_list_s {
+  char *interface;
+
+  uint32_t status;
+  uint32_t prev_status;
+  uint32_t sent;
+  cdtime_t timestamp;
+
+  struct interface_list_s *next;
+};
+typedef struct interface_list_s interface_list_t;
+
+/*
+ * Private variables
+ */
+
+static ignorelist_t *ignorelist = NULL;
+
+static interface_list_t *interface_list_head = NULL;
+static int monitor_all_interfaces = 1;
+
+static int connectivity_netlink_thread_loop = 0;
+static int connectivity_netlink_thread_error = 0;
+static pthread_t connectivity_netlink_thread_id;
+static int connectivity_dequeue_thread_loop = 0;
+static pthread_t connectivity_dequeue_thread_id;
+static pthread_mutex_t connectivity_threads_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t connectivity_data_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t connectivity_cond = PTHREAD_COND_INITIALIZER;
+static int nl_sock = -1;
+static int event_id = 0;
+static int statuses_to_send = 0;
+
+static const char *config_keys[] = {"Interface", "IgnoreSelected"};
+static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
+
+/*
+ * Private functions
+ */
+
+static int gen_message_payload(int state, int old_state, const char *interface,
+                               cdtime_t timestamp, char **buf) {
+  const unsigned char *buf2;
+  yajl_gen g;
+  char json_str[DATA_MAX_NAME_LEN];
+
+#if !defined(HAVE_YAJL_V2)
+  yajl_gen_config conf = {0};
+#endif
+
+#if HAVE_YAJL_V2
+  size_t len;
+  g = yajl_gen_alloc(NULL);
+  yajl_gen_config(g, yajl_gen_beautify, 0);
+#else
+  unsigned int len;
+  g = yajl_gen_alloc(&conf, NULL);
+#endif
+
+  yajl_gen_clear(g);
+
+  // *** BEGIN common event header ***
+
+  if (yajl_gen_map_open(g) != yajl_gen_status_ok)
+    goto err;
+
+  // domain
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_DOMAIN_FIELD,
+                      strlen(CONNECTIVITY_DOMAIN_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_DOMAIN_VALUE,
+                      strlen(CONNECTIVITY_DOMAIN_VALUE)) != yajl_gen_status_ok)
+    goto err;
+
+  // eventId
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_EVENT_ID_FIELD,
+                      strlen(CONNECTIVITY_EVENT_ID_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  event_id = event_id + 1;
+  if (snprintf(json_str, sizeof(json_str), "%d", event_id) < 0) {
+    goto err;
+  }
+
+  if (yajl_gen_number(g, json_str, strlen(json_str)) != yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // eventName
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_EVENT_NAME_FIELD,
+                      strlen(CONNECTIVITY_EVENT_NAME_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (snprintf(json_str, sizeof(json_str), "interface %s %s", interface,
+               (state == 0 ? CONNECTIVITY_EVENT_NAME_DOWN_VALUE
+                           : CONNECTIVITY_EVENT_NAME_UP_VALUE)) < 0) {
+    goto err;
+  }
+
+  if (yajl_gen_string(g, (u_char *)json_str, strlen(json_str)) !=
+      yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // lastEpochMicrosec
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_LAST_EPOCH_MICROSEC_FIELD,
+                      strlen(CONNECTIVITY_LAST_EPOCH_MICROSEC_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (snprintf(json_str, sizeof(json_str), "%" PRIu64,
+               CDTIME_T_TO_US(cdtime())) < 0) {
+    goto err;
+  }
+
+  if (yajl_gen_number(g, json_str, strlen(json_str)) != yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // priority
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_PRIORITY_FIELD,
+                      strlen(CONNECTIVITY_PRIORITY_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_PRIORITY_VALUE,
+                      strlen(CONNECTIVITY_PRIORITY_VALUE)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // reportingEntityName
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_REPORTING_ENTITY_NAME_FIELD,
+                      strlen(CONNECTIVITY_REPORTING_ENTITY_NAME_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_REPORTING_ENTITY_NAME_VALUE,
+                      strlen(CONNECTIVITY_REPORTING_ENTITY_NAME_VALUE)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // sequence
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_SEQUENCE_FIELD,
+                      strlen(CONNECTIVITY_SEQUENCE_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_number(g, CONNECTIVITY_SEQUENCE_VALUE,
+                      strlen(CONNECTIVITY_SEQUENCE_VALUE)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // sourceName
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_SOURCE_NAME_FIELD,
+                      strlen(CONNECTIVITY_SOURCE_NAME_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)interface, strlen(interface)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // startEpochMicrosec
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_START_EPOCH_MICROSEC_FIELD,
+                      strlen(CONNECTIVITY_START_EPOCH_MICROSEC_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (snprintf(json_str, sizeof(json_str), "%" PRIu64,
+               CDTIME_T_TO_US(timestamp)) < 0) {
+    goto err;
+  }
+
+  if (yajl_gen_number(g, json_str, strlen(json_str)) != yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // version
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_VERSION_FIELD,
+                      strlen(CONNECTIVITY_VERSION_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_number(g, CONNECTIVITY_VERSION_VALUE,
+                      strlen(CONNECTIVITY_VERSION_VALUE)) != yajl_gen_status_ok)
+    goto err;
+
+  // *** END common event header ***
+
+  // *** BEGIN state change fields ***
+
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_STATE_CHANGE_FIELDS_FIELD,
+                      strlen(CONNECTIVITY_STATE_CHANGE_FIELDS_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_map_open(g) != yajl_gen_status_ok)
+    goto err;
+
+  // newState
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_NEW_STATE_FIELD,
+                      strlen(CONNECTIVITY_NEW_STATE_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  int new_state_len =
+      (state == 0 ? strlen(CONNECTIVITY_NEW_STATE_FIELD_DOWN_VALUE)
+                  : strlen(CONNECTIVITY_NEW_STATE_FIELD_UP_VALUE));
+
+  if (yajl_gen_string(g,
+                      (u_char *)(state == 0
+                                     ? CONNECTIVITY_NEW_STATE_FIELD_DOWN_VALUE
+                                     : CONNECTIVITY_NEW_STATE_FIELD_UP_VALUE),
+                      new_state_len) != yajl_gen_status_ok)
+    goto err;
+
+  // oldState
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_OLD_STATE_FIELD,
+                      strlen(CONNECTIVITY_OLD_STATE_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  int old_state_len =
+      (old_state == 0 ? strlen(CONNECTIVITY_OLD_STATE_FIELD_DOWN_VALUE)
+                      : strlen(CONNECTIVITY_OLD_STATE_FIELD_UP_VALUE));
+
+  if (yajl_gen_string(g,
+                      (u_char *)(old_state == 0
+                                     ? CONNECTIVITY_OLD_STATE_FIELD_DOWN_VALUE
+                                     : CONNECTIVITY_OLD_STATE_FIELD_UP_VALUE),
+                      old_state_len) != yajl_gen_status_ok)
+    goto err;
+
+  // stateChangeFieldsVersion
+  if (yajl_gen_string(g,
+                      (u_char *)CONNECTIVITY_STATE_CHANGE_FIELDS_VERSION_FIELD,
+                      strlen(CONNECTIVITY_STATE_CHANGE_FIELDS_VERSION_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_number(g, CONNECTIVITY_STATE_CHANGE_FIELDS_VERSION_VALUE,
+                      strlen(CONNECTIVITY_STATE_CHANGE_FIELDS_VERSION_VALUE)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // stateInterface
+  if (yajl_gen_string(g, (u_char *)CONNECTIVITY_STATE_INTERFACE_FIELD,
+                      strlen(CONNECTIVITY_STATE_INTERFACE_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)interface, strlen(interface)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // close state change and header fields
+  if (yajl_gen_map_close(g) != yajl_gen_status_ok ||
+      yajl_gen_map_close(g) != yajl_gen_status_ok)
+    goto err;
+
+  // *** END state change fields ***
+
+  if (yajl_gen_get_buf(g, &buf2, &len) != yajl_gen_status_ok)
+    goto err;
+
+  *buf = strdup((char *)buf2);
+
+  if (*buf == NULL) {
+    ERROR("connectivity plugin: strdup failed during gen_message_payload: %s",
+          STRERRNO);
+    goto err;
+  }
+
+  yajl_gen_free(g);
+
+  return 0;
+
+err:
+  yajl_gen_free(g);
+  ERROR("connectivity plugin: gen_message_payload failed to generate JSON");
+  return -1;
+}
+
+static interface_list_t *add_interface(const char *interface, int status,
+                                       int prev_status) {
+  interface_list_t *il = calloc(1, sizeof(*il));
+
+  if (il == NULL) {
+    ERROR("connectivity plugin: calloc failed during add_interface: %s",
+          STRERRNO);
+    return NULL;
+  }
+
+  char *interface2 = strdup(interface);
+  if (interface2 == NULL) {
+    sfree(il);
+    ERROR("connectivity plugin: strdup failed during add_interface: %s",
+          STRERRNO);
+    return NULL;
+  }
+
+  il->interface = interface2;
+  il->status = status;
+  il->prev_status = prev_status;
+  il->timestamp = cdtime();
+  il->sent = 0;
+  il->next = interface_list_head;
+  interface_list_head = il;
+
+  DEBUG("connectivity plugin: added interface %s", interface2);
+
+  return il;
+}
+
+static int connectivity_link_state(struct nlmsghdr *msg) {
+  pthread_mutex_lock(&connectivity_data_lock);
+
+  struct nlattr *attr;
+  struct ifinfomsg *ifi = mnl_nlmsg_get_payload(msg);
+
+  /* Scan attribute list for device name. */
+  mnl_attr_for_each(attr, msg, sizeof(*ifi)) {
+    if (mnl_attr_get_type(attr) != IFLA_IFNAME)
+      continue;
+
+    if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
+      ERROR("connectivity plugin: connectivity_link_state: IFLA_IFNAME "
+            "mnl_attr_validate "
+            "failed.");
+      pthread_mutex_unlock(&connectivity_data_lock);
+      return MNL_CB_ERROR;
+    }
+
+    const char *dev = mnl_attr_get_str(attr);
+
+    // Check the list of interfaces we should monitor, if we've chosen
+    // a subset.  If we don't care about this one, abort.
+    if (ignorelist_match(ignorelist, dev) != 0) {
+      DEBUG("connectivity plugin: Ignoring link state change for unmonitored "
+            "interface: %s",
+            dev);
+      break;
+    }
+
+    interface_list_t *il = NULL;
+
+    for (il = interface_list_head; il != NULL; il = il->next)
+      if (strcmp(dev, il->interface) == 0)
+        break;
+
+    if (il == NULL) {
+      // We haven't encountered this interface yet, so add it to the linked list
+      il = add_interface(dev, LINK_STATE_UNKNOWN, LINK_STATE_UNKNOWN);
+
+      if (il == NULL) {
+        ERROR("connectivity plugin: unable to add interface %s during "
+              "connectivity_link_state",
+              dev);
+        return MNL_CB_ERROR;
+      }
+    }
+
+    uint32_t prev_status = il->status;
+    il->status =
+        ((ifi->ifi_flags & IFF_RUNNING) ? LINK_STATE_UP : LINK_STATE_DOWN);
+    il->timestamp = cdtime();
+
+    // If the new status is different than the previous status,
+    // store the previous status and set sent to zero, and set the
+    // global flag to indicate there are statuses to dispatch
+    if (il->status != prev_status) {
+      il->prev_status = prev_status;
+      il->sent = 0;
+      statuses_to_send = 1;
+    }
+
+    DEBUG("connectivity plugin (%llu): Interface %s status is now %s",
+          (unsigned long long)il->timestamp, dev,
+          ((ifi->ifi_flags & IFF_RUNNING) ? "UP" : "DOWN"));
+
+    // no need to loop again, we found the interface name attr
+    // (otherwise the first if-statement in the loop would
+    // have moved us on with 'continue')
+    break;
+  }
+
+  pthread_mutex_unlock(&connectivity_data_lock);
+
+  return 0;
+}
+
+static int msg_handler(struct nlmsghdr *msg) {
+  // We are only interested in RTM_NEWLINK messages
+  if (msg->nlmsg_type != RTM_NEWLINK) {
+    return 0;
+  }
+  return connectivity_link_state(msg);
+}
+
+static int read_event(int (*msg_handler)(struct nlmsghdr *)) {
+  int ret = 0;
+  int recv_flags = MSG_DONTWAIT;
+
+  if (nl_sock == -1 || msg_handler == NULL)
+    return EINVAL;
+
+  while (42) {
+    pthread_mutex_lock(&connectivity_threads_lock);
+
+    if (connectivity_netlink_thread_loop <= 0) {
+      pthread_mutex_unlock(&connectivity_threads_lock);
+      return ret;
+    }
+
+    pthread_mutex_unlock(&connectivity_threads_lock);
+
+    char buf[4096];
+    int status = recv(nl_sock, buf, sizeof(buf), recv_flags);
+
+    if (status < 0) {
+
+      // If there were no more messages to drain from the socket,
+      // then signal the dequeue thread and allow it to dispatch
+      // any saved interface status changes.  Then continue, but
+      // block and wait for new messages
+      if (errno == EWOULDBLOCK || errno == EAGAIN) {
+        pthread_cond_signal(&connectivity_cond);
+
+        recv_flags = 0;
+        continue;
+      }
+
+      if (errno == EINTR) {
+        // Interrupt, so just continue and try again
+        continue;
+      }
+
+      /* Anything else is an error */
+      ERROR("connectivity plugin: read_event: Error recv: %d", status);
+      return status;
+    }
+
+    // Message received successfully, so we'll stop blocking on the
+    // receive call for now (until we get a "would block" error, which
+    // will be handled above)
+    recv_flags = MSG_DONTWAIT;
+
+    if (status == 0) {
+      DEBUG("connectivity plugin: read_event: EOF");
+    }
+
+    /* We need to handle more than one message per 'recvmsg' */
+    for (struct nlmsghdr *h = (struct nlmsghdr *)buf;
+         NLMSG_OK(h, (unsigned int)status); h = NLMSG_NEXT(h, status)) {
+      /* Finish reading */
+      if (h->nlmsg_type == NLMSG_DONE)
+        return ret;
+
+      /* Message is some kind of error */
+      if (h->nlmsg_type == NLMSG_ERROR) {
+        struct nlmsgerr *l_err = (struct nlmsgerr *)NLMSG_DATA(h);
+        ERROR("connectivity plugin: read_event: Message is an error: %d",
+              l_err->error);
+        return -1; // Error
+      }
+
+      /* Call message handler */
+      if (msg_handler) {
+        ret = (*msg_handler)(h);
+        if (ret < 0) {
+          ERROR("connectivity plugin: read_event: Message handler error %d",
+                ret);
+          return ret;
+        }
+      } else {
+        ERROR("connectivity plugin: read_event: Error NULL message handler");
+        return -1;
+      }
+    }
+  }
+
+  return ret;
+}
+
+static void connectivity_dispatch_notification(const char *interface,
+                                               gauge_t value, gauge_t old_value,
+                                               cdtime_t timestamp) {
+
+  notification_t n = {
+      .severity = (value == LINK_STATE_UP ? NOTIF_OKAY : NOTIF_FAILURE),
+      .time = cdtime(),
+      .plugin = "connectivity",
+      .type = "gauge",
+      .type_instance = "interface_status",
+  };
+
+  sstrncpy(n.host, hostname_g, sizeof(n.host));
+  sstrncpy(n.plugin_instance, interface, sizeof(n.plugin_instance));
+
+  char *buf = NULL;
+
+  gen_message_payload(value, old_value, interface, timestamp, &buf);
+
+  int status = plugin_notification_meta_add_string(&n, "ves", buf);
+
+  if (status < 0) {
+    sfree(buf);
+    ERROR("connectivity plugin: unable to set notification VES metadata: %s",
+          STRERRNO);
+    return;
+  }
+
+  DEBUG("connectivity plugin: notification VES metadata: %s",
+        n.meta->nm_value.nm_string);
+
+  DEBUG("connectivity plugin: dispatching state %d for interface %s",
+        (int)value, interface);
+
+  plugin_dispatch_notification(&n);
+  plugin_notification_meta_free(n.meta);
+
+  // strdup'd in gen_message_payload
+  if (buf != NULL)
+    sfree(buf);
+}
+
+// NOTE: Caller MUST hold connectivity_data_lock when calling this function
+static void send_interface_status() {
+  for (interface_list_t *il = interface_list_head; il != NULL;
+       il = il->next) /* {{{ */
+  {
+    uint32_t status = il->status;
+    uint32_t prev_status = il->prev_status;
+    uint32_t sent = il->sent;
+
+    if (status != prev_status && sent == 0) {
+      connectivity_dispatch_notification(il->interface, status, prev_status,
+                                         il->timestamp);
+      il->sent = 1;
+    }
+  } /* }}} for (il = interface_list_head; il != NULL; il = il->next) */
+
+  statuses_to_send = 0;
+}
+
+static void read_interface_status() /* {{{ */
+{
+  pthread_mutex_lock(&connectivity_data_lock);
+
+  // If we don't have any interface statuses to dispatch,
+  // then we wait until signalled
+  if (!statuses_to_send)
+    pthread_cond_wait(&connectivity_cond, &connectivity_data_lock);
+
+  send_interface_status();
+
+  pthread_mutex_unlock(&connectivity_data_lock);
+} /* }}} int *read_interface_status */
+
+static void *connectivity_netlink_thread(void *arg) /* {{{ */
+{
+  pthread_mutex_lock(&connectivity_threads_lock);
+
+  while (connectivity_netlink_thread_loop > 0) {
+    pthread_mutex_unlock(&connectivity_threads_lock);
+
+    int status = read_event(msg_handler);
+
+    pthread_mutex_lock(&connectivity_threads_lock);
+
+    if (status < 0) {
+      connectivity_netlink_thread_error = 1;
+      break;
+    }
+  } /* while (connectivity_netlink_thread_loop > 0) */
+
+  pthread_mutex_unlock(&connectivity_threads_lock);
+
+  return (void *)0;
+} /* }}} void *connectivity_netlink_thread */
+
+static void *connectivity_dequeue_thread(void *arg) /* {{{ */
+{
+  pthread_mutex_lock(&connectivity_threads_lock);
+
+  while (connectivity_dequeue_thread_loop > 0) {
+    pthread_mutex_unlock(&connectivity_threads_lock);
+
+    read_interface_status();
+
+    pthread_mutex_lock(&connectivity_threads_lock);
+  } /* while (connectivity_dequeue_thread_loop > 0) */
+
+  pthread_mutex_unlock(&connectivity_threads_lock);
+
+  return ((void *)0);
+} /* }}} void *connectivity_dequeue_thread */
+
+static int nl_connect() {
+  struct sockaddr_nl sa_nl = {
+      .nl_family = AF_NETLINK,
+      .nl_groups = RTMGRP_LINK,
+      .nl_pid = getpid(),
+  };
+
+  nl_sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+  if (nl_sock == -1) {
+    ERROR("connectivity plugin: socket open failed: %s", STRERRNO);
+    return -1;
+  }
+
+  int rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
+  if (rc == -1) {
+    ERROR("connectivity plugin: socket bind failed: %s", STRERRNO);
+    close(nl_sock);
+    nl_sock = -1;
+    return -1;
+  }
+
+  return 0;
+}
+
+static int start_netlink_thread(void) /* {{{ */
+{
+  pthread_mutex_lock(&connectivity_threads_lock);
+
+  if (connectivity_netlink_thread_loop != 0) {
+    pthread_mutex_unlock(&connectivity_threads_lock);
+    return 0;
+  }
+
+  connectivity_netlink_thread_loop = 1;
+  connectivity_netlink_thread_error = 0;
+
+  int status;
+
+  if (nl_sock == -1) {
+    status = nl_connect();
+
+    if (status != 0) {
+      pthread_mutex_unlock(&connectivity_threads_lock);
+      return status;
+    }
+  }
+
+  status = plugin_thread_create(&connectivity_netlink_thread_id,
+                                /* attr = */ NULL, connectivity_netlink_thread,
+                                /* arg = */ (void *)0, "connectivity");
+  if (status != 0) {
+    connectivity_netlink_thread_loop = 0;
+    ERROR("connectivity plugin: Starting thread failed.");
+    pthread_mutex_unlock(&connectivity_threads_lock);
+
+    int status2 = close(nl_sock);
+
+    if (status2 != 0) {
+      ERROR("connectivity plugin: failed to close socket %d: %d (%s)", nl_sock,
+            status2, STRERRNO);
+    }
+
+    nl_sock = -1;
+
+    return -1;
+  }
+
+  pthread_mutex_unlock(&connectivity_threads_lock);
+
+  return status;
+}
+
+static int start_dequeue_thread(void) /* {{{ */
+{
+  pthread_mutex_lock(&connectivity_threads_lock);
+
+  if (connectivity_dequeue_thread_loop != 0) {
+    pthread_mutex_unlock(&connectivity_threads_lock);
+    return 0;
+  }
+
+  connectivity_dequeue_thread_loop = 1;
+
+  int status =
+      plugin_thread_create(&connectivity_dequeue_thread_id,
+                           /* attr = */ NULL, connectivity_dequeue_thread,
+                           /* arg = */ (void *)0, "connectivity");
+  if (status != 0) {
+    connectivity_dequeue_thread_loop = 0;
+    ERROR("connectivity plugin: Starting dequeue thread failed.");
+    pthread_mutex_unlock(&connectivity_threads_lock);
+    return -1;
+  }
+
+  pthread_mutex_unlock(&connectivity_threads_lock);
+
+  return status;
+} /* }}} int start_dequeue_thread */
+
+static int start_threads(void) /* {{{ */
+{
+  int status = start_netlink_thread();
+  int status2 = start_dequeue_thread();
+
+  if (status != 0)
+    return status;
+  else
+    return status2;
+} /* }}} int start_threads */
+
+static int stop_netlink_thread(int shutdown) /* {{{ */
+{
+  int socket_status;
+
+  if (nl_sock != -1) {
+    socket_status = close(nl_sock);
+    if (socket_status != 0) {
+      ERROR("connectivity plugin: failed to close socket %d: %d (%s)", nl_sock,
+            socket_status, STRERRNO);
+    }
+
+    nl_sock = -1;
+  } else
+    socket_status = 0;
+
+  pthread_mutex_lock(&connectivity_threads_lock);
+
+  if (connectivity_netlink_thread_loop == 0) {
+    pthread_mutex_unlock(&connectivity_threads_lock);
+    // Thread has already been terminated, nothing more to attempt
+    return socket_status;
+  }
+
+  // Set thread termination status
+  connectivity_netlink_thread_loop = 0;
+  pthread_mutex_unlock(&connectivity_threads_lock);
+
+  // Let threads waiting on access to the interface list know to move
+  // on such that they'll see the thread's termination status
+  pthread_cond_broadcast(&connectivity_cond);
+
+  int thread_status;
+
+  if (shutdown == 1) {
+    // Since the thread is blocking, calling pthread_join
+    // doesn't actually succeed in stopping it.  It will stick around
+    // until a NETLINK message is received on the socket (at which
+    // it will realize that "connectivity_netlink_thread_loop" is 0 and will
+    // break out of the read loop and be allowed to die).  This is
+    // fine when the process isn't supposed to be exiting, but in
+    // the case of a process shutdown, we don't want to have an
+    // idle thread hanging around.  Calling pthread_cancel here in
+    // the case of a shutdown is just assures that the thread is
+    // gone and that the process has been fully terminated.
+
+    DEBUG("connectivity plugin: Canceling netlink thread for process shutdown");
+
+    thread_status = pthread_cancel(connectivity_netlink_thread_id);
+
+    if (thread_status != 0 && thread_status != ESRCH) {
+      ERROR("connectivity plugin: Unable to cancel netlink thread: %d",
+            thread_status);
+      thread_status = -1;
+    } else
+      thread_status = 0;
+  } else {
+    thread_status =
+        pthread_join(connectivity_netlink_thread_id, /* return = */ NULL);
+    if (thread_status != 0 && thread_status != ESRCH) {
+      ERROR("connectivity plugin: Stopping netlink thread failed: %d",
+            thread_status);
+      thread_status = -1;
+    } else
+      thread_status = 0;
+  }
+
+  pthread_mutex_lock(&connectivity_threads_lock);
+  memset(&connectivity_netlink_thread_id, 0,
+         sizeof(connectivity_netlink_thread_id));
+  connectivity_netlink_thread_error = 0;
+  pthread_mutex_unlock(&connectivity_threads_lock);
+
+  DEBUG("connectivity plugin: Finished requesting stop of netlink thread");
+
+  if (socket_status != 0)
+    return socket_status;
+  else
+    return thread_status;
+}
+
+static int stop_dequeue_thread() /* {{{ */
+{
+  pthread_mutex_lock(&connectivity_threads_lock);
+
+  if (connectivity_dequeue_thread_loop == 0) {
+    pthread_mutex_unlock(&connectivity_threads_lock);
+    return -1;
+  }
+
+  // Set thread termination status
+  connectivity_dequeue_thread_loop = 0;
+  pthread_mutex_unlock(&connectivity_threads_lock);
+
+  // Let threads waiting on access to the interface list know to move
+  // on such that they'll see the threads termination status
+  pthread_cond_broadcast(&connectivity_cond);
+
+  // Calling pthread_cancel here just assures that the thread is
+  // gone and that the process has been fully terminated.
+
+  DEBUG("connectivity plugin: Canceling dequeue thread for process shutdown");
+
+  int status = pthread_cancel(connectivity_dequeue_thread_id);
+
+  if (status != 0 && status != ESRCH) {
+    ERROR("connectivity plugin: Unable to cancel dequeue thread: %d", status);
+    status = -1;
+  } else
+    status = 0;
+
+  pthread_mutex_lock(&connectivity_threads_lock);
+  memset(&connectivity_dequeue_thread_id, 0,
+         sizeof(connectivity_dequeue_thread_id));
+  pthread_mutex_unlock(&connectivity_threads_lock);
+
+  DEBUG("connectivity plugin: Finished requesting stop of dequeue thread");
+
+  return status;
+} /* }}} int stop_dequeue_thread */
+
+static int stop_threads() /* {{{ */
+{
+  int status = stop_netlink_thread(1);
+  int status2 = stop_dequeue_thread();
+
+  if (status != 0)
+    return status;
+  else
+    return status2;
+} /* }}} int stop_threads */
+
+static int connectivity_init(void) /* {{{ */
+{
+  if (monitor_all_interfaces) {
+    NOTICE("connectivity plugin: No interfaces have been selected, so all will "
+           "be monitored");
+  }
+
+  return start_threads();
+} /* }}} int connectivity_init */
+
+static int connectivity_config(const char *key, const char *value) /* {{{ */
+{
+  if (ignorelist == NULL) {
+    ignorelist = ignorelist_create(/* invert = */ 1);
+
+    if (ignorelist == NULL)
+      return -1;
+  }
+
+  if (strcasecmp(key, "Interface") == 0) {
+    ignorelist_add(ignorelist, value);
+    monitor_all_interfaces = 0;
+  } else if (strcasecmp(key, "IgnoreSelected") == 0) {
+    int invert = 1;
+    if (IS_TRUE(value))
+      invert = 0;
+    ignorelist_set_invert(ignorelist, invert);
+  } else {
+    return -1;
+  }
+
+  return 0;
+} /* }}} int connectivity_config */
+
+static int connectivity_read(void) /* {{{ */
+{
+  pthread_mutex_lock(&connectivity_threads_lock);
+
+  if (connectivity_netlink_thread_error != 0) {
+
+    pthread_mutex_unlock(&connectivity_threads_lock);
+
+    ERROR("connectivity plugin: The netlink thread had a problem. Restarting "
+          "it.");
+
+    stop_netlink_thread(0);
+
+    for (interface_list_t *il = interface_list_head; il != NULL;
+         il = il->next) {
+      il->status = LINK_STATE_UNKNOWN;
+      il->prev_status = LINK_STATE_UNKNOWN;
+      il->sent = 0;
+    }
+
+    start_netlink_thread();
+
+    return -1;
+  } /* if (connectivity_netlink_thread_error != 0) */
+
+  pthread_mutex_unlock(&connectivity_threads_lock);
+
+  return 0;
+} /* }}} int connectivity_read */
+
+static int connectivity_shutdown(void) /* {{{ */
+{
+  DEBUG("connectivity plugin: Shutting down thread.");
+
+  int status = stop_threads();
+
+  interface_list_t *il = interface_list_head;
+  while (il != NULL) {
+    interface_list_t *il_next;
+
+    il_next = il->next;
+
+    sfree(il->interface);
+    sfree(il);
+
+    il = il_next;
+  }
+
+  ignorelist_free(ignorelist);
+
+  return status;
+} /* }}} int connectivity_shutdown */
+
+void module_register(void) {
+  plugin_register_config("connectivity", connectivity_config, config_keys,
+                         config_keys_num);
+  plugin_register_init("connectivity", connectivity_init);
+  plugin_register_read("connectivity", connectivity_read);
+  plugin_register_shutdown("connectivity", connectivity_shutdown);
+} /* void module_register */
index acf3a74..d23d071 100644 (file)
 #include "plugin.h"
 #include "utils/common/common.h"
 
-#ifdef HAVE_SYS_SYSCTL_H
+#if defined(HAVE_SYSCTLBYNAME) && defined(HAVE_SYS_SYSCTL_H)
 #include <sys/sysctl.h>
-#endif
-
-#if HAVE_SYSCTLBYNAME
 /* no global variables */
 /* #endif HAVE_SYSCTLBYNAME */
 
@@ -73,7 +70,7 @@ static int cs_read(void) {
   }
 
   cs_submit(value);
-/* #endif HAVE_SYSCTLBYNAME */
+  /* #endif HAVE_SYSCTLBYNAME */
 
 #elif KERNEL_LINUX
   FILE *fh;
@@ -116,7 +113,7 @@ static int cs_read(void) {
 
   if (status == -2)
     ERROR("contextswitch plugin: Unable to find context switch value.");
-/* #endif  KERNEL_LINUX */
+    /* #endif  KERNEL_LINUX */
 
 #elif HAVE_PERFSTAT
   int status = 0;
index e7f3c18..8c1d4cb 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
 #include <sys/sysinfo.h>
 #endif /* HAVE_LIBKSTAT */
 
-#if (defined(HAVE_SYSCTL) && HAVE_SYSCTL) ||                                   \
-    (defined(HAVE_SYSCTLBYNAME) && HAVE_SYSCTLBYNAME)
-#ifdef HAVE_SYS_SYSCTL_H
+#if (defined(HAVE_SYSCTL) && defined(HAVE_SYSCTLBYNAME)) || defined(__OpenBSD__)
+/* Implies BSD variant */
 #include <sys/sysctl.h>
 #endif
 
 #ifdef HAVE_SYS_DKSTAT_H
+/* implies BSD variant */
 #include <sys/dkstat.h>
-#endif
 
 #if !defined(CP_USER) || !defined(CP_NICE) || !defined(CP_SYS) ||              \
     !defined(CP_INTR) || !defined(CP_IDLE) || !defined(CPUSTATES)
 #define CP_IDLE 4
 #define CPUSTATES 5
 #endif
-#endif /* HAVE_SYSCTL || HAVE_SYSCTLBYNAME */
+#endif /* HAVE_SYS_DKSTAT_H */
 
-#if HAVE_SYSCTL
+#define CAN_USE_SYSCTL 0
+#if (defined(HAVE_SYSCTL) && defined(HAVE_SYSCTLBYNAME)) || defined(__OpenBSD__)
+/* Implies BSD variant */
 #if defined(CTL_HW) && defined(HW_NCPU) && defined(CTL_KERN) &&                \
     defined(KERN_CPTIME) && defined(CPUSTATES)
 #define CAN_USE_SYSCTL 1
-#else
-#define CAN_USE_SYSCTL 0
-#endif
-#else
-#define CAN_USE_SYSCTL 0
 #endif
+#endif /* HAVE_SYSCTL_H && HAVE_SYSCTLBYNAME || __OpenBSD__ */
 
 #define COLLECTD_CPU_STATE_USER 0
 #define COLLECTD_CPU_STATE_SYSTEM 1
@@ -146,10 +143,12 @@ static int numcpu;
 /* #endif HAVE_LIBKSTAT */
 
 #elif CAN_USE_SYSCTL
+/* Only possible for (Open) BSD variant */
 static int numcpu;
 /* #endif CAN_USE_SYSCTL */
 
 #elif defined(HAVE_SYSCTLBYNAME)
+/* Implies BSD variant */
 static int numcpu;
 #ifdef HAVE_SYSCTL_KERN_CP_TIMES
 static int maxcpu;
@@ -251,7 +250,7 @@ static int init(void) {
 
   INFO("cpu plugin: Found %i processor%s.", (int)cpu_list_len,
        cpu_list_len == 1 ? "" : "s");
-/* #endif PROCESSOR_CPU_LOAD_INFO */
+  /* #endif PROCESSOR_CPU_LOAD_INFO */
 
 #elif defined(HAVE_LIBKSTAT)
   kstat_t *ksp_chain;
@@ -267,9 +266,10 @@ static int init(void) {
        ksp_chain = ksp_chain->ks_next)
     if (strncmp(ksp_chain->ks_module, "cpu_stat", 8) == 0)
       ksp[numcpu++] = ksp_chain;
-/* #endif HAVE_LIBKSTAT */
+      /* #endif HAVE_LIBKSTAT */
 
 #elif CAN_USE_SYSCTL
+  /* Only on (Open) BSD variant */
   size_t numcpu_size;
   int mib[2] = {CTL_HW, HW_NCPU};
   int status;
@@ -282,9 +282,10 @@ static int init(void) {
     WARNING("cpu plugin: sysctl: %s", STRERRNO);
     return -1;
   }
-/* #endif CAN_USE_SYSCTL */
+    /* #endif CAN_USE_SYSCTL */
 
 #elif defined(HAVE_SYSCTLBYNAME)
+  /* Only on BSD varient */
   size_t numcpu_size;
 
   numcpu_size = sizeof(numcpu);
@@ -307,7 +308,7 @@ static int init(void) {
            "%i)",
            numcpu);
 #endif
-/* #endif HAVE_SYSCTLBYNAME */
+    /* #endif HAVE_SYSCTLBYNAME */
 
 #elif defined(HAVE_LIBSTATGRAB)
 /* nothing to initialize */
@@ -630,7 +631,7 @@ static int cpu_read(void) {
     cpu_stage(cpu, COLLECTD_CPU_STATE_IDLE,
               (derive_t)cpu_info.cpu_ticks[CPU_STATE_IDLE], now);
   }
-/* }}} #endif PROCESSOR_CPU_LOAD_INFO */
+    /* }}} #endif PROCESSOR_CPU_LOAD_INFO */
 
 #elif defined(KERNEL_LINUX) /* {{{ */
   int cpu;
@@ -708,7 +709,7 @@ static int cpu_read(void) {
     cpu_stage(cpu, COLLECTD_CPU_STATE_NICE, (derive_t)nice_value, now);
   }
   fclose(fh);
-/* }}} #endif defined(KERNEL_LINUX) */
+  /* }}} #endif defined(KERNEL_LINUX) */
 
 #elif defined(HAVE_LIBKSTAT) /* {{{ */
   static cpu_stat_t cs;
@@ -729,9 +730,10 @@ static int cpu_read(void) {
     cpu_stage(ksp[cpu]->ks_instance, COLLECTD_CPU_STATE_WAIT,
               (derive_t)cs.cpu_sysinfo.cpu[CPU_WAIT], now);
   }
-/* }}} #endif defined(HAVE_LIBKSTAT) */
+    /* }}} #endif defined(HAVE_LIBKSTAT) */
 
 #elif CAN_USE_SYSCTL /* {{{ */
+  /* Only on (Open) BSD variant */
   uint64_t cpuinfo[numcpu][CPUSTATES];
   size_t cpuinfo_size;
   int status;
@@ -786,10 +788,11 @@ static int cpu_read(void) {
     cpu_stage(i, COLLECTD_CPU_STATE_INTERRUPT, (derive_t)cpuinfo[i][CP_INTR],
               now);
   }
-/* }}} #endif CAN_USE_SYSCTL */
+    /* }}} #endif CAN_USE_SYSCTL */
 
 #elif defined(HAVE_SYSCTLBYNAME) && defined(HAVE_SYSCTL_KERN_CP_TIMES) /* {{{  \
-                                                                          */
+                                                                        */
+  /* Only on BSD variant */
   long cpuinfo[maxcpu][CPUSTATES];
   size_t cpuinfo_size;
 
@@ -809,9 +812,10 @@ static int cpu_read(void) {
     cpu_stage(i, COLLECTD_CPU_STATE_INTERRUPT, (derive_t)cpuinfo[i][CP_INTR],
               now);
   }
-/* }}} #endif HAVE_SYSCTL_KERN_CP_TIMES */
+    /* }}} #endif HAVE_SYSCTL_KERN_CP_TIMES */
 
 #elif defined(HAVE_SYSCTLBYNAME) /* {{{ */
+  /* Only on BSD variant */
   long cpuinfo[CPUSTATES];
   size_t cpuinfo_size;
 
@@ -827,7 +831,7 @@ static int cpu_read(void) {
   cpu_stage(0, COLLECTD_CPU_STATE_SYSTEM, (derive_t)cpuinfo[CP_SYS], now);
   cpu_stage(0, COLLECTD_CPU_STATE_IDLE, (derive_t)cpuinfo[CP_IDLE], now);
   cpu_stage(0, COLLECTD_CPU_STATE_INTERRUPT, (derive_t)cpuinfo[CP_INTR], now);
-/* }}} #endif HAVE_SYSCTLBYNAME */
+  /* }}} #endif HAVE_SYSCTLBYNAME */
 
 #elif defined(HAVE_LIBSTATGRAB) /* {{{ */
   sg_cpu_stats *cs;
@@ -844,7 +848,7 @@ static int cpu_read(void) {
   cpu_state(0, COLLECTD_CPU_STATE_SYSTEM, (derive_t)cs->kernel);
   cpu_state(0, COLLECTD_CPU_STATE_USER, (derive_t)cs->user);
   cpu_state(0, COLLECTD_CPU_STATE_WAIT, (derive_t)cs->iowait);
-/* }}} #endif HAVE_LIBSTATGRAB */
+  /* }}} #endif HAVE_LIBSTATGRAB */
 
 #elif defined(HAVE_PERFSTAT) /* {{{ */
   perfstat_id_t id;
index b5cbe66..ee26b0b 100644 (file)
@@ -28,7 +28,7 @@
  * CPU sleep is reported in milliseconds of sleep per second of wall
  * time. For that, the time difference between BOOT and MONOTONIC clocks
  * is reported using derive type.
-**/
+ **/
 
 #include "collectd.h"
 
index 38951c0..11e64fa 100644 (file)
@@ -181,7 +181,7 @@ extern PyTypeObject ValuesType;
 
 typedef struct {
   PluginData data;
-  PyObject *meta;   /* dict */
+  PyObject *meta; /* dict */
   int severity;
   char message[NOTIF_MAX_MSG_LEN];
 } Notification;
index e3e3c17..7eb4805 100644 (file)
@@ -541,7 +541,8 @@ static int cc_config_add_page(oconfig_item_t *ci) /* {{{ */
   plugin_register_complex_read(/* group = */ NULL, cb_name, cc_read_page,
                                interval,
                                &(user_data_t){
-                                   .data = page, .free_func = cc_web_page_free,
+                                   .data = page,
+                                   .free_func = cc_web_page_free,
                                });
   sfree(cb_name);
 
index 9d01e6e..edfaf00 100644 (file)
@@ -763,7 +763,8 @@ static int cj_config_add_url(oconfig_item_t *ci) /* {{{ */
 
     plugin_register_complex_read(/* group = */ NULL, cb_name, cj_read, interval,
                                  &(user_data_t){
-                                     .data = db, .free_func = cj_free,
+                                     .data = db,
+                                     .free_func = cj_free,
                                  });
     sfree(cb_name);
   } else {
index ce6bd46..4524ac3 100644 (file)
@@ -697,8 +697,8 @@ static int cx_config_add_namespace(cx_t *db, /* {{{ */
     return EINVAL;
   }
 
-  cx_namespace_t *ns = realloc(
-      db->namespaces, sizeof(*db->namespaces) * (db->namespaces_num + 1));
+  cx_namespace_t *ns = realloc(db->namespaces, sizeof(*db->namespaces) *
+                                                   (db->namespaces_num + 1));
   if (ns == NULL) {
     ERROR("curl_xml plugin: realloc failed.");
     return ENOMEM;
@@ -925,7 +925,8 @@ static int cx_config_add_url(oconfig_item_t *ci) /* {{{ */
   plugin_register_complex_read(/* group = */ "curl_xml", cb_name, cx_read,
                                /* interval = */ interval,
                                &(user_data_t){
-                                   .data = db, .free_func = cx_free,
+                                   .data = db,
+                                   .free_func = cx_free,
                                });
   sfree(cb_name);
   return 0;
index 49f9272..09aee6a 100644 (file)
@@ -182,7 +182,7 @@ int main(int argc, char **argv) {
 #ifdef KERNEL_LINUX
       && notify_upstart() == 0 && notify_systemd() == 0
 #endif
-      ) {
+  ) {
     pid_t pid;
     if ((pid = fork()) == -1) {
       /* error */
index ae2d327..78d410c 100644 (file)
@@ -307,11 +307,12 @@ static int do_shutdown(void) {
 static void read_cmdline(int argc, char **argv, struct cmdline_config *config) {
   /* read options */
   while (1) {
-    int c = getopt(argc, argv, "BhtTC:"
+    int c = getopt(argc, argv,
+                   "BhtTC:"
 #if COLLECT_DAEMON
-                               "fP:"
+                   "fP:"
 #endif
-                   );
+    );
 
     if (c == -1)
       break;
@@ -391,7 +392,9 @@ void stop_collectd(void) { loop++; }
 
 struct cmdline_config init_config(int argc, char **argv) {
   struct cmdline_config config = {
-      .daemonize = true, .create_basedir = true, .configfile = CONFIGFILE,
+      .daemonize = true,
+      .create_basedir = true,
+      .configfile = CONFIGFILE,
   };
 
   read_cmdline(argc, argv, &config);
index 735be83..61fa901 100644 (file)
@@ -137,40 +137,58 @@ static cf_callback_t *cf_search(const char *type) {
   return cf_cb;
 }
 
-static int cf_dispatch(const char *type, const char *orig_key,
-                       const char *orig_value) {
-  cf_callback_t *cf_cb;
-  plugin_ctx_t old_ctx;
-  char *key;
-  char *value;
-  int ret;
-  int i = 0;
+static int cf_dispatch_option(const cf_callback_t *cf_cb, oconfig_item_t *ci) {
 
+  const char *plugin = cf_cb->type;
+  const char *orig_key = ci->key;
   if (orig_key == NULL)
     return EINVAL;
 
-  DEBUG("type = %s, key = %s, value = %s", ESCAPE_NULL(type), orig_key,
-        ESCAPE_NULL(orig_value));
+  /* (Re)construct string value for option */
+  char buffer[4096];
+  int buffer_free = sizeof(buffer);
+  char *buffer_ptr = buffer;
 
-  if ((cf_cb = cf_search(type)) == NULL) {
-    WARNING("Found a configuration for the `%s' plugin, but "
-            "the plugin isn't loaded or didn't register "
-            "a configuration callback.",
-            type);
-    return -1;
+  for (int i = 0; i < ci->values_num; i++) {
+    int status = -1;
+
+    if (ci->values[i].type == OCONFIG_TYPE_STRING)
+      status =
+          ssnprintf(buffer_ptr, buffer_free, " %s", ci->values[i].value.string);
+    else if (ci->values[i].type == OCONFIG_TYPE_NUMBER)
+      status = ssnprintf(buffer_ptr, buffer_free, " %lf",
+                         ci->values[i].value.number);
+    else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN)
+      status = ssnprintf(buffer_ptr, buffer_free, " %s",
+                         ci->values[i].value.boolean ? "true" : "false");
+
+    if ((status < 0) || (status >= buffer_free))
+      return -1;
+    buffer_free -= status;
+    buffer_ptr += status;
   }
 
-  if ((key = strdup(orig_key)) == NULL)
+  /* skip the initial space */
+  const char *orig_value = buffer + 1;
+
+  DEBUG("plugin = %s, key = %s, value = %s", ESCAPE_NULL(plugin), orig_key,
+        ESCAPE_NULL(orig_value));
+
+  char *key = strdup(orig_key);
+  if (key == NULL)
     return 1;
-  if ((value = strdup(orig_value)) == NULL) {
+
+  char *value = strdup(orig_value);
+  if (value == NULL) {
     free(key);
     return 2;
   }
 
-  ret = -1;
+  int ret = -1;
 
-  old_ctx = plugin_set_ctx(cf_cb->ctx);
+  plugin_ctx_t old_ctx = plugin_set_ctx(cf_cb->ctx);
 
+  int i;
   for (i = 0; i < cf_cb->keys_num; i++) {
     if ((cf_cb->keys[i] != NULL) && (strcasecmp(cf_cb->keys[i], key) == 0)) {
       ret = (*cf_cb->callback)(key, value);
@@ -181,13 +199,13 @@ static int cf_dispatch(const char *type, const char *orig_key,
   plugin_set_ctx(old_ctx);
 
   if (i >= cf_cb->keys_num)
-    WARNING("Plugin `%s' did not register for value `%s'.", type, key);
+    WARNING("Plugin `%s' did not register for value `%s'.", plugin, key);
 
   free(key);
   free(value);
 
   return ret;
-} /* int cf_dispatch */
+} /* int cf_dispatch_option */
 
 static int dispatch_global_option(const oconfig_item_t *ci) {
   if (ci->values_num != 1) {
@@ -200,7 +218,7 @@ static int dispatch_global_option(const oconfig_item_t *ci) {
     return global_option_set(ci->key, ci->values[0].value.string, 0);
   else if (ci->values[0].type == OCONFIG_TYPE_NUMBER) {
     char tmp[128];
-    snprintf(tmp, sizeof(tmp), "%lf", ci->values[0].value.number);
+    ssnprintf(tmp, sizeof(tmp), "%lf", ci->values[0].value.number);
     return global_option_set(ci->key, tmp, 0);
   } else if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN) {
     if (ci->values[0].value.boolean)
@@ -267,7 +285,8 @@ static int dispatch_loadplugin(oconfig_item_t *ci) {
 
   /* default to the global interval set before loading this plugin */
   plugin_ctx_t ctx = {
-      .interval = cf_get_default_interval(), .name = strdup(name),
+      .interval = cf_get_default_interval(),
+      .name = strdup(name),
   };
   if (ctx.name == NULL)
     return ENOMEM;
@@ -298,38 +317,6 @@ static int dispatch_loadplugin(oconfig_item_t *ci) {
   return ret_val;
 } /* int dispatch_value_loadplugin */
 
-static int dispatch_value_plugin(const char *plugin, oconfig_item_t *ci) {
-  char buffer[4096];
-  char *buffer_ptr;
-  int buffer_free;
-
-  buffer_ptr = buffer;
-  buffer_free = sizeof(buffer);
-
-  for (int i = 0; i < ci->values_num; i++) {
-    int status = -1;
-
-    if (ci->values[i].type == OCONFIG_TYPE_STRING)
-      status =
-          snprintf(buffer_ptr, buffer_free, " %s", ci->values[i].value.string);
-    else if (ci->values[i].type == OCONFIG_TYPE_NUMBER)
-      status =
-          snprintf(buffer_ptr, buffer_free, " %lf", ci->values[i].value.number);
-    else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN)
-      status = snprintf(buffer_ptr, buffer_free, " %s",
-                        ci->values[i].value.boolean ? "true" : "false");
-
-    if ((status < 0) || (status >= buffer_free))
-      return -1;
-    buffer_free -= status;
-    buffer_ptr += status;
-  }
-  /* skip the initial space */
-  buffer_ptr = buffer + 1;
-
-  return cf_dispatch(plugin, ci->key, buffer_ptr);
-} /* int dispatch_value_plugin */
-
 static int dispatch_value(oconfig_item_t *ci) {
   int ret = 0;
 
@@ -363,67 +350,88 @@ static int dispatch_block_plugin(oconfig_item_t *ci) {
     return -1;
   }
 
-  const char *name = ci->values[0].value.string;
-  if (strcmp("libvirt", name) == 0) {
+  const char *plugin_name = ci->values[0].value.string;
+  if (strcmp("libvirt", plugin_name) == 0) {
     /* TODO(octo): Remove this legacy. */
     WARNING("The \"libvirt\" plugin has been renamed to \"virt\" to avoid "
             "problems with the build system. "
             "Your configuration is still using the old name. "
             "Please change it to use \"virt\" as soon as possible. "
             "This compatibility code will go away eventually.");
-    name = "virt";
+    plugin_name = "virt";
   }
 
-  if (IS_TRUE(global_option_get("AutoLoadPlugin"))) {
+  bool plugin_loaded = plugin_is_loaded(plugin_name);
+
+  if (!plugin_loaded && IS_TRUE(global_option_get("AutoLoadPlugin"))) {
     plugin_ctx_t ctx = {0};
-    plugin_ctx_t old_ctx;
-    int status;
 
     /* default to the global interval set before loading this plugin */
     ctx.interval = cf_get_default_interval();
-    ctx.name = strdup(name);
+    ctx.name = strdup(plugin_name);
 
-    old_ctx = plugin_set_ctx(ctx);
-    status = plugin_load(name, /* flags = */ false);
+    plugin_ctx_t old_ctx = plugin_set_ctx(ctx);
+    int status = plugin_load(plugin_name, /* flags = */ false);
     /* reset to the "global" context */
     plugin_set_ctx(old_ctx);
 
     if (status != 0) {
-      ERROR("Automatically loading plugin \"%s\" failed "
+      ERROR("Automatically loading plugin `%s' failed "
             "with status %i.",
-            name, status);
+            plugin_name, status);
       return status;
     }
+    plugin_loaded = true;
+  }
+
+  if (!plugin_loaded) {
+    WARNING("There is configuration for the `%s' plugin, but the plugin isn't "
+            "loaded. Please check your configuration.",
+            plugin_name);
+
+    /* Try to be backward-compatible with previous versions */
+    return 0;
   }
 
   /* Check for a complex callback first */
   for (cf_complex_callback_t *cb = complex_callback_head; cb != NULL;
        cb = cb->next) {
-    if (strcasecmp(name, cb->type) == 0) {
-      plugin_ctx_t old_ctx;
-      int ret_val;
-
-      old_ctx = plugin_set_ctx(cb->ctx);
-      ret_val = (cb->callback(ci));
+    if (strcasecmp(plugin_name, cb->type) == 0) {
+      plugin_ctx_t old_ctx = plugin_set_ctx(cb->ctx);
+      int ret_val = (cb->callback(ci));
       plugin_set_ctx(old_ctx);
       return ret_val;
     }
   }
 
+  /* Try to be backward-compatible with previous versions */
+  if (ci->children_num == 0)
+    return 0;
+
   /* Hm, no complex plugin found. Dispatch the values one by one */
-  for (int i = 0, ret = 0; i < ci->children_num; i++) {
+  cf_callback_t *cf_cb = cf_search(plugin_name);
+  if (cf_cb == NULL) {
+    WARNING("Found a configuration for the `%s' plugin, but "
+            "the plugin didn't register a configuration callback.",
+            plugin_name);
+    return -1;
+  }
+
+  for (int i = 0; i < ci->children_num; i++) {
     if (ci->children[i].children == NULL) {
-      ret = dispatch_value_plugin(name, ci->children + i);
-      if (ret != 0)
+      oconfig_item_t *child = ci->children + i;
+      int ret = cf_dispatch_option(cf_cb, child);
+      if (ret != 0) {
+        ERROR("Plugin `%s' failed to handle option `%s', return code: %i",
+              plugin_name, child->key, ret);
         return ret;
+      }
     } else {
       WARNING("There is a `%s' block within the "
-              "configuration for the %s plugin. "
-              "The plugin either only expects "
-              "\"simple\" configuration statements "
-              "or wasn't loaded using `LoadPlugin'."
-              " Please check your configuration.",
-              ci->children[i].key, name);
+              "configuration for the `%s' plugin. "
+              "The plugin only expects \"simple\" configuration options. "
+              "Blocks are not supported. Please check your configuration.",
+              ci->children[i].key, plugin_name);
     }
   }
 
@@ -475,9 +483,9 @@ static int cf_ci_replace_child(oconfig_item_t *dst, oconfig_item_t *src,
     return 0;
   }
 
-  temp = realloc(dst->children,
-                 sizeof(oconfig_item_t) *
-                     (dst->children_num + src->children_num - 1));
+  temp =
+      realloc(dst->children, sizeof(oconfig_item_t) *
+                                 (dst->children_num + src->children_num - 1));
   if (temp == NULL) {
     ERROR("configfile: realloc failed.");
     return -1;
@@ -516,9 +524,8 @@ static int cf_ci_append_children(oconfig_item_t *dst, oconfig_item_t *src) {
   if ((src == NULL) || (src->children_num == 0))
     return 0;
 
-  temp =
-      realloc(dst->children,
-              sizeof(oconfig_item_t) * (dst->children_num + src->children_num));
+  temp = realloc(dst->children, sizeof(oconfig_item_t) *
+                                    (dst->children_num + src->children_num));
   if (temp == NULL) {
     ERROR("configfile: realloc failed.");
     return -1;
@@ -666,7 +673,7 @@ static oconfig_item_t *cf_read_dir(const char *dir, const char *pattern,
     if ((de->d_name[0] == '.') || (de->d_name[0] == 0))
       continue;
 
-    status = snprintf(name, sizeof(name), "%s/%s", dir, de->d_name);
+    status = ssnprintf(name, sizeof(name), "%s/%s", dir, de->d_name);
     if ((status < 0) || ((size_t)status >= sizeof(name))) {
       ERROR("configfile: Not including `%s/%s' because its"
             " name is too long.",
@@ -806,7 +813,7 @@ static oconfig_item_t *cf_read_generic(const char *path, const char *pattern,
 
   return root;
 } /* oconfig_item_t *cf_read_generic */
-/* #endif HAVE_WORDEXP_H */
+  /* #endif HAVE_WORDEXP_H */
 
 #else  /* if !HAVE_WORDEXP_H */
 static oconfig_item_t *cf_read_generic(const char *path, const char *pattern,
@@ -1235,7 +1242,7 @@ int cf_util_get_service(const oconfig_item_t *ci, char **ret_string) /* {{{ */
     P_ERROR("cf_util_get_service: Out of memory.");
     return -1;
   }
-  snprintf(service, 6, "%i", port);
+  ssnprintf(service, 6, "%i", port);
 
   sfree(*ret_string);
   *ret_string = service;
index a76a44c..85f1b11 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  **/
 
-#include "globals.h"
+// clang-format off
+/*
+ * Explicit order is required or _FILE_OFFSET_BITS will have definition mismatches on Solaris
+ * See Github Issue #3193 for details
+ */
 #include "utils/common/common.h"
+#include "globals.h"
+// clang-format on
 
 #if HAVE_KSTAT_H
 #include <kstat.h>
index b4e5ae7..52cb0a4 100644 (file)
@@ -85,6 +85,14 @@ struct read_func_s {
 };
 typedef struct read_func_s read_func_t;
 
+struct cache_event_func_s {
+  plugin_cache_event_cb callback;
+  char *name;
+  user_data_t user_data;
+  plugin_ctx_t plugin_ctx;
+};
+typedef struct cache_event_func_s cache_event_func_t;
+
 struct write_queue_s;
 typedef struct write_queue_s write_queue_t;
 struct write_queue_s {
@@ -112,6 +120,9 @@ static llist_t *list_shutdown;
 static llist_t *list_log;
 static llist_t *list_notification;
 
+static size_t list_cache_event_num;
+static cache_event_func_t list_cache_event[32];
+
 static fc_chain_t *pre_cache_chain;
 static fc_chain_t *post_cache_chain;
 
@@ -263,8 +274,6 @@ static void destroy_read_heap(void) /* {{{ */
 
 static int register_callback(llist_t **list, /* {{{ */
                              const char *name, callback_func_t *cf) {
-  llentry_t *le;
-  char *key;
 
   if (*list == NULL) {
     *list = llist_create();
@@ -276,14 +285,14 @@ static int register_callback(llist_t **list, /* {{{ */
     }
   }
 
-  key = strdup(name);
+  char *key = strdup(name);
   if (key == NULL) {
     ERROR("plugin: register_callback: strdup failed.");
     destroy_callback(cf);
     return -1;
   }
 
-  le = llist_search(*list, name);
+  llentry_t *le = llist_search(*list, name);
   if (le == NULL) {
     le = llentry_create(key, cf);
     if (le == NULL) {
@@ -296,9 +305,7 @@ static int register_callback(llist_t **list, /* {{{ */
 
     llist_append(*list, le);
   } else {
-    callback_func_t *old_cf;
-
-    old_cf = le->value;
+    callback_func_t *old_cf = le->value;
     le->value = cf;
 
     P_WARNING("register_callback: "
@@ -366,7 +373,8 @@ static int create_register_callback(llist_t **list, /* {{{ */
   cf->cf_callback = callback;
   if (ud == NULL) {
     cf->cf_udata = (user_data_t){
-        .data = NULL, .free_func = NULL,
+        .data = NULL,
+        .free_func = NULL,
     };
   } else {
     cf->cf_udata = *ud;
@@ -646,7 +654,8 @@ static void start_read_threads(size_t num) /* {{{ */
     }
 
     char name[THREAD_NAME_MAX];
-    snprintf(name, sizeof(name), "reader#%" PRIu64, (uint64_t)read_threads_num);
+    ssnprintf(name, sizeof(name), "reader#%" PRIu64,
+              (uint64_t)read_threads_num);
     set_thread_name(read_threads[read_threads_num], name);
 
     read_threads_num++;
@@ -835,8 +844,8 @@ static void start_write_threads(size_t num) /* {{{ */
     }
 
     char name[THREAD_NAME_MAX];
-    snprintf(name, sizeof(name), "writer#%" PRIu64,
-             (uint64_t)write_threads_num);
+    ssnprintf(name, sizeof(name), "writer#%" PRIu64,
+              (uint64_t)write_threads_num);
     set_thread_name(write_threads[write_threads_num], name);
 
     write_threads_num++;
@@ -905,15 +914,13 @@ void plugin_set_dir(const char *dir) {
     ERROR("plugin_set_dir: strdup(\"%s\") failed", dir);
 }
 
-static bool plugin_is_loaded(char const *name) {
-  int status;
-
+bool plugin_is_loaded(char const *name) {
   if (plugins_loaded == NULL)
     plugins_loaded =
         c_avl_create((int (*)(const void *, const void *))strcasecmp);
   assert(plugins_loaded != NULL);
 
-  status = c_avl_get(plugins_loaded, name, /* ret_value = */ NULL);
+  int status = c_avl_get(plugins_loaded, name, /* ret_value = */ NULL);
   return status == 0;
 }
 
@@ -1294,8 +1301,10 @@ EXPORT int plugin_register_flush(const char *name, plugin_flush_cb callback,
         /* name      = */ flush_name,
         /* callback  = */ plugin_flush_timeout_callback,
         /* interval  = */ ctx.flush_interval,
-        /* user data = */ &(user_data_t){
-            .data = cb, .free_func = plugin_flush_timeout_callback_free,
+        /* user data = */
+        &(user_data_t){
+            .data = cb,
+            .free_func = plugin_flush_timeout_callback_free,
         });
 
     sfree(flush_name);
@@ -1310,6 +1319,60 @@ EXPORT int plugin_register_missing(const char *name, plugin_missing_cb callback,
   return create_register_callback(&list_missing, name, (void *)callback, ud);
 } /* int plugin_register_missing */
 
+EXPORT int plugin_register_cache_event(const char *name,
+                                       plugin_cache_event_cb callback,
+                                       user_data_t const *ud) {
+
+  if (name == NULL || callback == NULL)
+    return EINVAL;
+
+  char *name_copy = strdup(name);
+  if (name_copy == NULL) {
+    P_ERROR("plugin_register_cache_event: strdup failed.");
+    free_userdata(ud);
+    return ENOMEM;
+  }
+
+  if (list_cache_event_num >= 32) {
+    P_ERROR("plugin_register_cache_event: Too much cache event callbacks tried "
+            "to be registered.");
+    free_userdata(ud);
+    return ENOMEM;
+  }
+
+  for (size_t i = 0; i < list_cache_event_num; i++) {
+    cache_event_func_t *cef = &list_cache_event[i];
+    if (!cef->callback)
+      continue;
+
+    if (strcmp(name, cef->name) == 0) {
+      P_ERROR("plugin_register_cache_event: a callback named `%s' already "
+              "registered!",
+              name);
+      free_userdata(ud);
+      return -1;
+    }
+  }
+
+  user_data_t user_data;
+  if (ud == NULL) {
+    user_data = (user_data_t){
+        .data = NULL, .free_func = NULL,
+    };
+  } else {
+    user_data = *ud;
+  }
+
+  list_cache_event[list_cache_event_num] =
+      (cache_event_func_t){.callback = callback,
+                           .name = name_copy,
+                           .user_data = user_data,
+                           .plugin_ctx = plugin_get_ctx()};
+  list_cache_event_num++;
+
+  return 0;
+} /* int plugin_register_cache_event */
+
 EXPORT int plugin_register_shutdown(const char *name, int (*callback)(void)) {
   return create_register_callback(&list_shutdown, name, (void *)callback, NULL);
 } /* int plugin_register_shutdown */
@@ -1511,6 +1574,32 @@ EXPORT int plugin_unregister_missing(const char *name) {
   return plugin_unregister(list_missing, name);
 }
 
+EXPORT int plugin_unregister_cache_event(const char *name) {
+  for (size_t i = 0; i < list_cache_event_num; i++) {
+    cache_event_func_t *cef = &list_cache_event[i];
+    if (!cef->callback)
+      continue;
+    if (strcmp(name, cef->name) == 0) {
+      /* Mark callback as inactive, so mask in cache entries remains actual */
+      cef->callback = NULL;
+      sfree(cef->name);
+      free_userdata(&cef->user_data);
+    }
+  }
+  return 0;
+}
+
+static void destroy_cache_event_callbacks() {
+  for (size_t i = 0; i < list_cache_event_num; i++) {
+    cache_event_func_t *cef = &list_cache_event[i];
+    if (!cef->callback)
+      continue;
+    cef->callback = NULL;
+    sfree(cef->name);
+    free_userdata(&cef->user_data);
+  }
+}
+
 EXPORT int plugin_unregister_shutdown(const char *name) {
   return plugin_unregister(list_shutdown, name);
 }
@@ -1855,6 +1944,7 @@ EXPORT int plugin_shutdown_all(void) {
    * the data isn't freed twice. */
   destroy_all_callbacks(&list_flush);
   destroy_all_callbacks(&list_missing);
+  destroy_cache_event_callbacks();
   destroy_all_callbacks(&list_write);
 
   destroy_all_callbacks(&list_notification);
@@ -1895,6 +1985,82 @@ EXPORT int plugin_dispatch_missing(const value_list_t *vl) /* {{{ */
   return 0;
 } /* int }}} plugin_dispatch_missing */
 
+void plugin_dispatch_cache_event(enum cache_event_type_e event_type,
+                                 unsigned long callbacks_mask, const char *name,
+                                 const value_list_t *vl) {
+  switch (event_type) {
+  case CE_VALUE_NEW:
+    callbacks_mask = 0;
+    for (size_t i = 0; i < list_cache_event_num; i++) {
+      cache_event_func_t *cef = &list_cache_event[i];
+      plugin_cache_event_cb callback = cef->callback;
+
+      if (!callback)
+        continue;
+
+      cache_event_t event = (cache_event_t){.type = event_type,
+                                            .value_list = vl,
+                                            .value_list_name = name,
+                                            .ret = 0};
+
+      plugin_ctx_t old_ctx = plugin_set_ctx(cef->plugin_ctx);
+      int status = (*callback)(&event, &cef->user_data);
+      plugin_set_ctx(old_ctx);
+
+      if (status != 0) {
+        ERROR("plugin_dispatch_cache_event: Callback \"%s\" failed with status "
+              "%i for event NEW.",
+              cef->name, status);
+      } else {
+        if (event.ret) {
+          DEBUG(
+              "plugin_dispatch_cache_event: Callback \"%s\" subscribed to %s.",
+              cef->name, name);
+          callbacks_mask |= (1 << (i));
+        } else {
+          DEBUG("plugin_dispatch_cache_event: Callback \"%s\" ignores %s.",
+                cef->name, name);
+        }
+      }
+    }
+
+    if (callbacks_mask)
+      uc_set_callbacks_mask(name, callbacks_mask);
+
+    break;
+  case CE_VALUE_UPDATE:
+  case CE_VALUE_EXPIRED:
+    for (size_t i = 0; i < list_cache_event_num; i++) {
+      cache_event_func_t *cef = &list_cache_event[i];
+      plugin_cache_event_cb callback = cef->callback;
+
+      if (!callback)
+        continue;
+
+      if (callbacks_mask && (1 << (i)) == 0)
+        continue;
+
+      cache_event_t event = (cache_event_t){.type = event_type,
+                                            .value_list = vl,
+                                            .value_list_name = name,
+                                            .ret = 0};
+
+      plugin_ctx_t old_ctx = plugin_set_ctx(cef->plugin_ctx);
+      int status = (*callback)(&event, &cef->user_data);
+      plugin_set_ctx(old_ctx);
+
+      if (status != 0) {
+        ERROR("plugin_dispatch_cache_event: Callback \"%s\" failed with status "
+              "%i for event %s.",
+              cef->name, status,
+              ((event_type == CE_VALUE_UPDATE) ? "UPDATE" : "EXPIRED"));
+      }
+    }
+    break;
+  }
+  return;
+}
+
 static int plugin_dispatch_values_internal(value_list_t *vl) {
   int status;
   static c_complain_t no_write_complaint = C_COMPLAIN_INIT_STATIC;
index 6b3a030..af3693d 100644 (file)
@@ -171,6 +171,15 @@ struct user_data_s {
 };
 typedef struct user_data_s user_data_t;
 
+enum cache_event_type_e { CE_VALUE_NEW, CE_VALUE_UPDATE, CE_VALUE_EXPIRED };
+
+typedef struct cache_event_s {
+  enum cache_event_type_e type;
+  const value_list_t *value_list;
+  const char *value_list_name;
+  int ret;
+} cache_event_t;
+
 struct plugin_ctx_s {
   char *name;
   cdtime_t interval;
@@ -192,6 +201,11 @@ typedef int (*plugin_flush_cb)(cdtime_t timeout, const char *identifier,
  * callbacks should be called, greater than zero if no more callbacks should be
  * called. */
 typedef int (*plugin_missing_cb)(const value_list_t *, user_data_t *);
+/* "cache event" callback. CE_VALUE_NEW events are sent to all registered
+ * callbacks. Callback should check if it interested in further CE_VALUE_UPDATE
+ * and CE_VALUE_EXPIRED events for metric and set event->ret = 1 if so.
+ */
+typedef int (*plugin_cache_event_cb)(cache_event_t *, user_data_t *);
 typedef void (*plugin_log_cb)(int severity, const char *message, user_data_t *);
 typedef int (*plugin_shutdown_cb)(void);
 typedef int (*plugin_notification_cb)(const notification_t *, user_data_t *);
@@ -233,6 +247,7 @@ void plugin_set_dir(const char *dir);
  *  this case.
  */
 int plugin_load(const char *name, bool global);
+bool plugin_is_loaded(char const *name);
 
 int plugin_init_all(void);
 void plugin_read_all(void);
@@ -294,6 +309,9 @@ int plugin_register_flush(const char *name, plugin_flush_cb callback,
                           user_data_t const *user_data);
 int plugin_register_missing(const char *name, plugin_missing_cb callback,
                             user_data_t const *user_data);
+int plugin_register_cache_event(const char *name,
+                                plugin_cache_event_cb callback,
+                                user_data_t const *ud);
 int plugin_register_shutdown(const char *name, plugin_shutdown_cb callback);
 int plugin_register_data_set(const data_set_t *ds);
 int plugin_register_log(const char *name, plugin_log_cb callback,
@@ -310,6 +328,7 @@ int plugin_unregister_read_group(const char *group);
 int plugin_unregister_write(const char *name);
 int plugin_unregister_flush(const char *name);
 int plugin_unregister_missing(const char *name);
+int plugin_unregister_cache_event(const char *name);
 int plugin_unregister_shutdown(const char *name);
 int plugin_unregister_data_set(const char *name);
 int plugin_unregister_log(const char *name);
@@ -380,6 +399,9 @@ __attribute__((sentinel)) int plugin_dispatch_multivalue(value_list_t const *vl,
                                                          int store_type, ...);
 
 int plugin_dispatch_missing(const value_list_t *vl);
+void plugin_dispatch_cache_event(enum cache_event_type_e event_type,
+                                 unsigned long callbacks_mask, const char *name,
+                                 const value_list_t *vl);
 
 int plugin_dispatch_notification(const notification_t *notif);
 
index 1624f0e..69d5e28 100644 (file)
@@ -41,6 +41,8 @@ void plugin_set_dir(const char *dir) { /* nop */
 
 int plugin_load(const char *name, bool global) { return ENOTSUP; }
 
+bool plugin_is_loaded(const char *name) { return false; }
+
 int plugin_register_config(const char *name,
                            int (*callback)(const char *key, const char *val),
                            const char **keys, int keys_num) {
@@ -67,6 +69,13 @@ int plugin_register_write(__attribute__((unused)) const char *name,
   return ENOTSUP;
 }
 
+int plugin_register_flush(__attribute__((unused)) const char *name,
+                          __attribute__((unused)) plugin_flush_cb callback,
+                          __attribute__((unused))
+                          user_data_t const *user_data) {
+  return ENOTSUP;
+}
+
 int plugin_register_missing(const char *name, plugin_missing_cb callback,
                             user_data_t const *ud) {
   return ENOTSUP;
@@ -85,6 +94,31 @@ int plugin_register_shutdown(const char *name, int (*callback)(void)) {
 
 int plugin_register_data_set(const data_set_t *ds) { return ENOTSUP; }
 
+int plugin_register_notification(__attribute__((unused)) const char *name,
+                                 __attribute__((unused))
+                                 plugin_notification_cb callback,
+                                 __attribute__((unused))
+                                 user_data_t const *user_data) {
+  return ENOTSUP;
+}
+
+#define DECLARE_UNREGISTER(t)                                                  \
+  int plugin_unregister_##t(__attribute__((unused)) char const *name) {        \
+    return ENOTSUP;                                                            \
+  }
+DECLARE_UNREGISTER(config)
+DECLARE_UNREGISTER(complex_config)
+DECLARE_UNREGISTER(init)
+DECLARE_UNREGISTER(read)
+DECLARE_UNREGISTER(read_group)
+DECLARE_UNREGISTER(write)
+DECLARE_UNREGISTER(flush)
+DECLARE_UNREGISTER(missing)
+DECLARE_UNREGISTER(shutdown)
+DECLARE_UNREGISTER(data_set)
+DECLARE_UNREGISTER(log)
+DECLARE_UNREGISTER(notification)
+
 int plugin_dispatch_values(value_list_t const *vl) { return ENOTSUP; }
 
 int plugin_dispatch_notification(__attribute__((unused))
@@ -198,6 +232,14 @@ plugin_ctx_t plugin_set_ctx(plugin_ctx_t ctx) {
 
 cdtime_t plugin_get_interval(void) { return mock_context.interval; }
 
+int plugin_thread_create(__attribute__((unused)) pthread_t *thread,
+                         __attribute__((unused)) const pthread_attr_t *attr,
+                         __attribute__((unused)) void *(*start_routine)(void *),
+                         __attribute__((unused)) void *arg,
+                         __attribute__((unused)) char const *name) {
+  return ENOTSUP;
+}
+
 /* TODO(octo): this function is actually from filter_chain.h, but in order not
  * to tumble down that rabbit hole, we're declaring it here. A better solution
  * would be to hard-code the top-level config keys in daemon/collectd.c to avoid
index c53e5d1..cf2095e 100644 (file)
@@ -67,6 +67,7 @@ typedef struct cache_entry_s {
   size_t history_length;
 
   meta_data_t *meta;
+  unsigned long callbacks_mask;
 } cache_entry_t;
 
 struct uc_iter_s {
@@ -140,18 +141,15 @@ static void uc_check_range(const data_set_t *ds, cache_entry_t *ce) {
 
 static int uc_insert(const data_set_t *ds, const value_list_t *vl,
                      const char *key) {
-  char *key_copy;
-  cache_entry_t *ce;
-
   /* `cache_lock' has been locked by `uc_update' */
 
-  key_copy = strdup(key);
+  char *key_copy = strdup(key);
   if (key_copy == NULL) {
     ERROR("uc_insert: strdup failed.");
     return -1;
   }
 
-  ce = cache_alloc(ds->ds_num);
+  cache_entry_t *ce = cache_alloc(ds->ds_num);
   if (ce == NULL) {
     sfree(key_copy);
     ERROR("uc_insert: cache_alloc (%" PRIsz ") failed.", ds->ds_num);
@@ -203,6 +201,10 @@ static int uc_insert(const data_set_t *ds, const value_list_t *vl,
   ce->interval = vl->interval;
   ce->state = STATE_UNKNOWN;
 
+  if (vl->meta != NULL) {
+    ce->meta = meta_data_clone(vl->meta);
+  }
+
   if (c_avl_insert(cache_tree, key_copy, ce) != 0) {
     sfree(key_copy);
     ERROR("uc_insert: c_avl_insert failed.");
@@ -226,6 +228,7 @@ int uc_check_timeout(void) {
     char *key;
     cdtime_t time;
     cdtime_t interval;
+    unsigned long callbacks_mask;
   } *expired = NULL;
   size_t expired_num = 0;
 
@@ -251,6 +254,7 @@ int uc_check_timeout(void) {
     expired[expired_num].key = strdup(key);
     expired[expired_num].time = ce->last_time;
     expired[expired_num].interval = ce->interval;
+    expired[expired_num].callbacks_mask = ce->callbacks_mask;
 
     if (expired[expired_num].key == NULL) {
       ERROR("uc_check_timeout: strdup failed.");
@@ -275,7 +279,8 @@ int uc_check_timeout(void) {
    * plugin calls the cache interface. */
   for (size_t i = 0; i < expired_num; i++) {
     value_list_t vl = {
-        .time = expired[i].time, .interval = expired[i].interval,
+        .time = expired[i].time,
+        .interval = expired[i].interval,
     };
 
     if (parse_identifier_vl(expired[i].key, &vl) != 0) {
@@ -285,6 +290,10 @@ int uc_check_timeout(void) {
     }
 
     plugin_dispatch_missing(&vl);
+
+    if (expired[i].callbacks_mask)
+      plugin_dispatch_cache_event(CE_VALUE_EXPIRED, expired[i].callbacks_mask,
+                                  expired[i].key, &vl);
   } /* for (i = 0; i < expired_num; i++) */
 
   /* Now actually remove all the values from the cache. We don't re-evaluate
@@ -314,8 +323,6 @@ int uc_check_timeout(void) {
 
 int uc_update(const data_set_t *ds, const value_list_t *vl) {
   char name[6 * DATA_MAX_NAME_LEN];
-  cache_entry_t *ce = NULL;
-  int status;
 
   if (FORMAT_VL(name, sizeof(name), vl) != 0) {
     ERROR("uc_update: FORMAT_VL failed.");
@@ -324,11 +331,16 @@ int uc_update(const data_set_t *ds, const value_list_t *vl) {
 
   pthread_mutex_lock(&cache_lock);
 
-  status = c_avl_get(cache_tree, name, (void *)&ce);
+  cache_entry_t *ce = NULL;
+  int status = c_avl_get(cache_tree, name, (void *)&ce);
   if (status != 0) /* entry does not yet exist */
   {
     status = uc_insert(ds, vl, name);
     pthread_mutex_unlock(&cache_lock);
+
+    if (status == 0)
+      plugin_dispatch_cache_event(CE_VALUE_NEW, 0 /* mask */, name, vl);
+
     return status;
   }
 
@@ -403,11 +415,32 @@ int uc_update(const data_set_t *ds, const value_list_t *vl) {
   ce->last_update = cdtime();
   ce->interval = vl->interval;
 
+  /* Check if cache entry has registered callbacks */
+  unsigned long callbacks_mask = ce->callbacks_mask;
+
   pthread_mutex_unlock(&cache_lock);
 
+  if (callbacks_mask)
+    plugin_dispatch_cache_event(CE_VALUE_UPDATE, callbacks_mask, name, vl);
+
   return 0;
 } /* int uc_update */
 
+int uc_set_callbacks_mask(const char *name, unsigned long mask) {
+  pthread_mutex_lock(&cache_lock);
+  cache_entry_t *ce = NULL;
+  int status = c_avl_get(cache_tree, name, (void *)&ce);
+  if (status != 0) { /* Ouch, just created entry disappeared ?! */
+    ERROR("uc_set_callbacks_mask: Couldn't find %s entry!", name);
+    pthread_mutex_unlock(&cache_lock);
+    return -1;
+  }
+  DEBUG("uc_set_callbacks_mask: set mask for \"%s\" to %lu.", name, mask);
+  ce->callbacks_mask = mask;
+  pthread_mutex_unlock(&cache_lock);
+  return 0;
+}
+
 int uc_get_rate_by_name(const char *name, gauge_t **ret_values,
                         size_t *ret_values_num) {
   gauge_t *ret = NULL;
@@ -889,13 +922,12 @@ int uc_iterator_get_values(uc_iter_t *iter, value_t **ret_values,
   if ((iter == NULL) || (iter->entry == NULL) || (ret_values == NULL) ||
       (ret_num == NULL))
     return -1;
-
   *ret_values =
       calloc(iter->entry->values_num, sizeof(*iter->entry->values_raw));
   if (*ret_values == NULL)
     return -1;
   for (size_t i = 0; i < iter->entry->values_num; ++i)
-    *ret_values[i] = iter->entry->values_raw[i];
+    (*ret_values)[i] = iter->entry->values_raw[i];
 
   *ret_num = iter->entry->values_num;
 
@@ -966,11 +998,17 @@ static meta_data_t *uc_get_meta(const value_list_t *vl) /* {{{ */
     pthread_mutex_unlock(&cache_lock);                                         \
     return status;                                                             \
   }
-int uc_meta_data_exists(const value_list_t *vl,
-                        const char *key) UC_WRAP(meta_data_exists)
+int uc_meta_data_exists(const value_list_t *vl, const char *key)
+    UC_WRAP(meta_data_exists)
+
+        int uc_meta_data_delete(const value_list_t *vl, const char *key)
+            UC_WRAP(meta_data_delete)
+
+    /* The second argument is called `toc` in the API, but the macro expects
+     * `key`. */
+    int uc_meta_data_toc(const value_list_t *vl,
+                         char ***key) UC_WRAP(meta_data_toc)
 
-    int uc_meta_data_delete(const value_list_t *vl,
-                            const char *key) UC_WRAP(meta_data_delete)
 #undef UC_WRAP
 
 /* We need a new version of this macro because the following functions take
index d3ea936..9050477 100644 (file)
@@ -56,6 +56,8 @@ int uc_get_hits(const data_set_t *ds, const value_list_t *vl);
 int uc_set_hits(const data_set_t *ds, const value_list_t *vl, int hits);
 int uc_inc_hits(const data_set_t *ds, const value_list_t *vl, int step);
 
+int uc_set_callbacks_mask(const char *name, unsigned long callbacks_mask);
+
 int uc_get_history(const data_set_t *ds, const value_list_t *vl,
                    gauge_t *ret_history, size_t num_steps, size_t num_ds);
 int uc_get_history_by_name(const char *name, gauge_t *ret_history,
@@ -116,6 +118,8 @@ int uc_iterator_get_meta(uc_iter_t *iter, meta_data_t **ret_meta);
  */
 int uc_meta_data_exists(const value_list_t *vl, const char *key);
 int uc_meta_data_delete(const value_list_t *vl, const char *key);
+/* Same API as meta_data_toc. */
+int uc_meta_data_toc(const value_list_t *vl, char ***toc);
 
 int uc_meta_data_add_string(const value_list_t *vl, const char *key,
                             const char *value);
index 75bdc12..ff0022e 100644 (file)
@@ -24,6 +24,9 @@
  *   Florian Forster <octo at collectd.org>
  **/
 
+#ifndef UTILS_RANDOM_H
+#define UTILS_RANDOM_H 1
+
 /**
  * Returns a random double value in the range [0..1), i.e. excluding 1.
  *
@@ -46,3 +49,5 @@ uint32_t cdrand_u(void);
  * outside the intended range. This function is thread- and reentrant-safe.
  */
 long cdrand_range(long min, long max);
+
+#endif /* !UTILS_RANDOM_H */
index e73a5c0..c02b6ab 100644 (file)
@@ -59,9 +59,6 @@
 #include <libgeom.h>
 #endif
 
-#if HAVE_LIMITS_H
-#include <limits.h>
-#endif
 #ifndef UINT_MAX
 #define UINT_MAX 4294967295U
 #endif
@@ -209,7 +206,7 @@ static int disk_init(void) {
     io_master_port = MACH_PORT_NULL;
     return -1;
   }
-/* #endif HAVE_IOKIT_IOKITLIB_H */
+    /* #endif HAVE_IOKIT_IOKITLIB_H */
 
 #elif KERNEL_LINUX
 #if HAVE_LIBUDEV_H
@@ -221,7 +218,7 @@ static int disk_init(void) {
     }
   }
 #endif /* HAVE_LIBUDEV_H */
-/* #endif KERNEL_LINUX */
+    /* #endif KERNEL_LINUX */
 
 #elif KERNEL_FREEBSD
   int rv;
@@ -236,7 +233,7 @@ static int disk_init(void) {
     ERROR("geom_stats_open() failed, returned %d", rv);
     return -1;
   }
-/* #endif KERNEL_FREEBSD */
+    /* #endif KERNEL_FREEBSD */
 
 #elif HAVE_LIBKSTAT
   kstat_t *ksp_chain;
@@ -275,7 +272,8 @@ static void disk_submit(const char *plugin_instance, const char *type,
                         derive_t read, derive_t write) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = read}, {.derive = write},
+      {.derive = read},
+      {.derive = write},
   };
 
   vl.values = values;
@@ -292,7 +290,8 @@ static void submit_io_time(char const *plugin_instance, derive_t io_time,
                            derive_t weighted_time) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = io_time}, {.derive = weighted_time},
+      {.derive = io_time},
+      {.derive = weighted_time},
   };
 
   vl.values = values;
@@ -493,10 +492,11 @@ static int disk_read(void) {
         sstrncpy(disk_name, props_disk_name_bsd, sizeof(disk_name));
       else {
         ERROR("disk plugin: can't find bsd disk name.");
-        snprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major, disk_minor);
+        ssnprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major,
+                  disk_minor);
       }
     } else
-      snprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major, disk_minor);
+      ssnprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major, disk_minor);
 
     DEBUG("disk plugin: disk_name = \"%s\"", disk_name);
 
@@ -532,7 +532,7 @@ static int disk_read(void) {
       disk_submit(disk_name, "disk_time", read_tme / 1000, write_tme / 1000);
   }
   IOObjectRelease(disk_list);
-/* #endif HAVE_IOKIT_IOKITLIB_H */
+  /* #endif HAVE_IOKIT_IOKITLIB_H */
 
 #elif KERNEL_FREEBSD
   int retry, dirty;
@@ -896,7 +896,7 @@ static int disk_read(void) {
     free(missing_ds);
   }
   fclose(fh);
-/* #endif defined(KERNEL_LINUX) */
+  /* #endif defined(KERNEL_LINUX) */
 
 #elif HAVE_LIBKSTAT
 #if HAVE_KSTAT_IO_T_WRITES && HAVE_KSTAT_IO_T_NWRITES && HAVE_KSTAT_IO_T_WTIME
@@ -944,7 +944,7 @@ static int disk_read(void) {
       disk_submit(ksp[i]->ks_name, "disk_ops", kio.KIO_ROPS, kio.KIO_WOPS);
     }
   }
-/* #endif defined(HAVE_LIBKSTAT) */
+    /* #endif defined(HAVE_LIBKSTAT) */
 
 #elif defined(HAVE_LIBSTATGRAB)
   sg_disk_io_stats *ds;
@@ -971,7 +971,7 @@ static int disk_read(void) {
     disk_submit(name, "disk_octets", ds->read_bytes, ds->write_bytes);
     ds++;
   }
-/* #endif defined(HAVE_LIBSTATGRAB) */
+    /* #endif defined(HAVE_LIBSTATGRAB) */
 
 #elif defined(HAVE_PERFSTAT)
   derive_t read_sectors;
index 7fa297b..dad0be2 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -324,7 +324,8 @@ static void submit_derive(const char *type, const char *type_instance,
 
 static void submit_octets(derive_t queries, derive_t responses) {
   value_t values[] = {
-      {.derive = queries}, {.derive = responses},
+      {.derive = queries},
+      {.derive = responses},
   };
   value_list_t vl = VALUE_LIST_INIT;
 
index 4cdf01d..4c8196a 100644 (file)
@@ -511,17 +511,17 @@ static int dpdk_events_link_status_dispatch(dpdk_helper_ctx_t *phc) {
 
         char dev_name[DATA_MAX_NAME_LEN];
         if (ec->config.link_status.port_name[i][0] != 0) {
-          snprintf(dev_name, sizeof(dev_name), "%s",
-                   ec->config.link_status.port_name[i]);
+          ssnprintf(dev_name, sizeof(dev_name), "%s",
+                    ec->config.link_status.port_name[i]);
         } else {
-          snprintf(dev_name, sizeof(dev_name), "port.%d", i);
+          ssnprintf(dev_name, sizeof(dev_name), "port.%d", i);
         }
 
         if (ec->config.link_status.notify) {
           int sev = ec->link_info[i].link_status ? NOTIF_OKAY : NOTIF_WARNING;
           char msg[DATA_MAX_NAME_LEN];
-          snprintf(msg, sizeof(msg), "Link Status: %s",
-                   ec->link_info[i].link_status ? "UP" : "DOWN");
+          ssnprintf(msg, sizeof(msg), "Link Status: %s",
+                    ec->link_info[i].link_status ? "UP" : "DOWN");
           dpdk_events_notification_dispatch(sev, dev_name,
                                             ec->link_info[i].read_time, msg);
         } else {
@@ -557,7 +557,7 @@ static void dpdk_events_keep_alive_dispatch(dpdk_helper_ctx_t *phc) {
     }
 
     char core_name[DATA_MAX_NAME_LEN];
-    snprintf(core_name, sizeof(core_name), "lcore%u", i);
+    ssnprintf(core_name, sizeof(core_name), "lcore%u", i);
 
     if (!ec->config.keep_alive.send_updated ||
         (ec->core_info[i].lcore_state !=
@@ -572,34 +572,34 @@ static void dpdk_events_keep_alive_dispatch(dpdk_helper_ctx_t *phc) {
         switch (ec->config.keep_alive.shm->core_state[i]) {
         case RTE_KA_STATE_ALIVE:
           sev = NOTIF_OKAY;
-          snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: ALIVE", i);
+          ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: ALIVE", i);
           break;
         case RTE_KA_STATE_MISSING:
-          snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: MISSING", i);
+          ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: MISSING", i);
           sev = NOTIF_WARNING;
           break;
         case RTE_KA_STATE_DEAD:
-          snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: DEAD", i);
+          ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: DEAD", i);
           sev = NOTIF_FAILURE;
           break;
         case RTE_KA_STATE_UNUSED:
-          snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: UNUSED", i);
+          ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: UNUSED", i);
           sev = NOTIF_OKAY;
           break;
         case RTE_KA_STATE_GONE:
-          snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: GONE", i);
+          ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: GONE", i);
           sev = NOTIF_FAILURE;
           break;
         case RTE_KA_STATE_DOZING:
-          snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: DOZING", i);
+          ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: DOZING", i);
           sev = NOTIF_OKAY;
           break;
         case RTE_KA_STATE_SLEEP:
-          snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: SLEEP", i);
+          ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: SLEEP", i);
           sev = NOTIF_OKAY;
           break;
         default:
-          snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: UNKNOWN", i);
+          ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: UNKNOWN", i);
           sev = NOTIF_FAILURE;
         }
 
index 0005d09..ae93e53 100644 (file)
@@ -395,9 +395,9 @@ static int dpdk_stats_counters_dispatch(dpdk_helper_ctx_t *phc) {
 
     char dev_name[64];
     if (ctx->config.port_name[i][0] != 0) {
-      snprintf(dev_name, sizeof(dev_name), "%s", ctx->config.port_name[i]);
+      ssnprintf(dev_name, sizeof(dev_name), "%s", ctx->config.port_name[i]);
     } else {
-      snprintf(dev_name, sizeof(dev_name), "port.%d", i);
+      ssnprintf(dev_name, sizeof(dev_name), "port.%d", i);
     }
 
     DEBUG(" === Dispatch stats for port %d (name=%s; stats_count=%d)", i,
index deb6600..5360205 100644 (file)
@@ -174,16 +174,18 @@ static int email_config(const char *key, const char *value) {
     long int tmp = strtol(value, NULL, 0);
 
     if (tmp < 1) {
-      fprintf(stderr, "email plugin: `MaxConns' was set to invalid "
-                      "value %li, will use default %i.\n",
+      fprintf(stderr,
+              "email plugin: `MaxConns' was set to invalid "
+              "value %li, will use default %i.\n",
               tmp, MAX_CONNS);
       ERROR("email plugin: `MaxConns' was set to invalid "
             "value %li, will use default %i.\n",
             tmp, MAX_CONNS);
       max_conns = MAX_CONNS;
     } else if (tmp > MAX_CONNS_LIMIT) {
-      fprintf(stderr, "email plugin: `MaxConns' was set to invalid "
-                      "value %li, will use hardcoded limit %i.\n",
+      fprintf(stderr,
+              "email plugin: `MaxConns' was set to invalid "
+              "value %li, will use hardcoded limit %i.\n",
               tmp, MAX_CONNS_LIMIT);
       ERROR("email plugin: `MaxConns' was set to invalid "
             "value %li, will use hardcoded limit %i.\n",
index 7e16167..f8707d4 100644 (file)
@@ -26,6 +26,9 @@
 #define _DEFAULT_SOURCE
 #define _BSD_SOURCE /* For setgroups */
 
+/* _GNU_SOURCE is needed in Linux to use execvpe */
+#define _GNU_SOURCE
+
 #include "collectd.h"
 
 #include "plugin.h"
@@ -43,6 +46,8 @@
 #include <sys/capability.h>
 #endif
 
+extern char **environ;
+
 #define PL_NORMAL 0x01
 #define PL_NOTIF_ACTION 0x02
 
@@ -245,49 +250,9 @@ static int exec_config(oconfig_item_t *ci) /* {{{ */
   return 0;
 } /* int exec_config }}} */
 
-#if !defined(HAVE_SETENV)
-static char env_interval[64];
-// max hostname len is 255, so this should be enough
-static char env_hostname[300];
-#endif
-
-static void set_environment(void) /* {{{ */
-{
-#ifdef HAVE_SETENV
-  char buffer[1024];
-
-  snprintf(buffer, sizeof(buffer), "%.3f",
-           CDTIME_T_TO_DOUBLE(plugin_get_interval()));
-  setenv("COLLECTD_INTERVAL", buffer, /* overwrite = */ 1);
-
-  sstrncpy(buffer, hostname_g, sizeof(buffer));
-  setenv("COLLECTD_HOSTNAME", buffer, /* overwrite = */ 1);
-#else
-  snprintf(env_interval, sizeof(env_interval), "COLLECTD_INTERVAL=%.3f",
-           CDTIME_T_TO_DOUBLE(plugin_get_interval()));
-  putenv(env_interval);
-
-  snprintf(env_hostname, sizeof(env_hostname), "COLLECTD_HOSTNAME=%s",
-           hostname_g);
-  putenv(env_hostname);
-#endif
-} /* }}} void set_environment */
-
-static void unset_environment(void) /* {{{ */
-{
-#ifdef HAVE_SETENV
-  unsetenv("COLLECTD_INTERVAL");
-  unsetenv("COLLECTD_HOSTNAME");
-#else
-  snprintf(env_interval, sizeof(env_interval), "COLLECTD_INTERVAL");
-  putenv(env_interval);
-  snprintf(env_hostname, sizeof(env_hostname), "COLLECTD_HOSTNAME");
-  putenv(env_hostname);
-#endif
-} /* }}} void unset_environment */
-
-__attribute__((noreturn)) static void exec_child(program_list_t *pl, int uid,
-                                                 int gid, int egid) /* {{{ */
+__attribute__((noreturn)) static void exec_child(program_list_t *pl,
+                                                 char **envp, int uid, int gid,
+                                                 int egid) /* {{{ */
 {
   int status;
 
@@ -328,7 +293,12 @@ __attribute__((noreturn)) static void exec_child(program_list_t *pl, int uid,
     exit(-1);
   }
 
+#ifdef HAVE_EXECVPE
+  execvpe(pl->exec, pl->argv, envp);
+#else
+  environ = envp;
   execvp(pl->exec, pl->argv);
+#endif
 
   ERROR("exec plugin: Failed to execute ``%s'': %s", pl->exec, STRERRNO);
   exit(-1);
@@ -486,17 +456,42 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out,
     goto failed;
   }
 
-  set_environment();
+  double interval = CDTIME_T_TO_DOUBLE(plugin_get_interval());
 
   pid = fork();
   if (pid < 0) {
     ERROR("exec plugin: fork failed: %s", STRERRNO);
     goto failed;
   } else if (pid == 0) {
-    int fd_num;
+    char interval_buf[128];
+    snprintf(interval_buf, sizeof(interval_buf), "COLLECTD_INTERVAL=%.3f",
+             interval);
+
+    /* max hostname len is 255, so this should be enough */
+    char hostname_buf[300];
+    snprintf(hostname_buf, sizeof(hostname_buf), "COLLECTD_HOSTNAME=%s",
+             hostname_g);
+
+    size_t env_size = 0;
+    while (environ[env_size] != NULL) {
+      ++env_size;
+    }
+
+    /* Copy the environment variables */
+    char *envp[env_size + 3];
+    size_t envp_idx;
+    for (envp_idx = 0; environ[envp_idx] != NULL && envp_idx < env_size;
+         ++envp_idx) {
+      envp[envp_idx] = environ[envp_idx];
+    }
+
+    /* Add the collectd environment variables */
+    envp[envp_idx++] = interval_buf;
+    envp[envp_idx++] = hostname_buf;
+    envp[envp_idx++] = NULL;
 
     /* Close all file descriptors but the pipe end we need. */
-    fd_num = getdtablesize();
+    int fd_num = getdtablesize();
     for (int fd = 0; fd < fd_num; fd++) {
       if ((fd == fd_pipe_in[0]) || (fd == fd_pipe_out[1]) ||
           (fd == fd_pipe_err[1]))
@@ -525,12 +520,10 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out,
     /* Unblock all signals */
     reset_signal_mask();
 
-    exec_child(pl, uid, gid, egid);
+    exec_child(pl, envp, uid, gid, egid);
     /* does not return */
   }
 
-  unset_environment();
-
   close(fd_pipe_in[0]);
   close(fd_pipe_out[1]);
   close(fd_pipe_err[1]);
@@ -553,8 +546,6 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out,
   return pid;
 
 failed:
-  unset_environment();
-
   close_pipe(fd_pipe_in);
   close_pipe(fd_pipe_out);
   close_pipe(fd_pipe_err);
@@ -754,8 +745,9 @@ static void *exec_notification_one(void *arg) /* {{{ */
   else if (n->severity == NOTIF_OKAY)
     severity = "OKAY";
 
-  fprintf(fh, "Severity: %s\n"
-              "Time: %.3f\n",
+  fprintf(fh,
+          "Severity: %s\n"
+          "Time: %.3f\n",
           severity, CDTIME_T_TO_DOUBLE(n->time));
 
   /* Print the optional fields */
@@ -918,6 +910,11 @@ static int exec_shutdown(void) /* {{{ */
       INFO("exec plugin: Sent SIGTERM to %hu", (unsigned short int)pl->pid);
     }
 
+    for (int i = 0; pl->argv[i] != NULL; i++) {
+      sfree(pl->argv[i]);
+    }
+    sfree(pl->argv);
+    sfree(pl->exec);
     sfree(pl->user);
     sfree(pl);
 
index b14dee3..03dedcc 100644 (file)
@@ -397,8 +397,8 @@ static staging_entry_t *staging_entry_get(const char *host, /* {{{ */
   if (staging_tree == NULL)
     return NULL;
 
-  snprintf(key, sizeof(key), "%s/%s/%s", host, type,
-           (type_instance != NULL) ? type_instance : "");
+  ssnprintf(key, sizeof(key), "%s/%s/%s", host, type,
+            (type_instance != NULL) ? type_instance : "");
 
   se = NULL;
   status = c_avl_get(staging_tree, key, (void *)&se);
index d76e503..f176795 100644 (file)
@@ -54,7 +54,8 @@ static char *nv_errline = "";
 #define KEY_IGNORESELECTED "IgnoreSelected"
 
 static const char *config_keys[] = {
-    KEY_GPUINDEX, KEY_IGNORESELECTED,
+    KEY_GPUINDEX,
+    KEY_IGNORESELECTED,
 };
 static const unsigned int n_config_keys = STATIC_ARRAY_SIZE(config_keys);
 
index 1e9cb20..d9577a4 100644 (file)
@@ -747,7 +747,8 @@ static int c_grpc_config_server(oconfig_item_t *ci) {
 
   auto callback_name = grpc::string("grpc/") + addr;
   user_data_t ud = {
-      .data = client, .free_func = c_grpc_destroy_write_callback,
+      .data = client,
+      .free_func = c_grpc_destroy_write_callback,
   };
 
   plugin_register_write(callback_name.c_str(), c_grpc_write, &ud);
index a68620e..99c3ed0 100644 (file)
@@ -105,7 +105,7 @@ static void rdt_submit_derive(const char *cgroup, const char *type,
   vl.values_len = 1;
 
   sstrncpy(vl.plugin, RDT_PLUGIN, sizeof(vl.plugin));
-  snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s", cgroup);
+  ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s", cgroup);
   sstrncpy(vl.type, type, sizeof(vl.type));
   if (type_instance)
     sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
@@ -121,7 +121,7 @@ static void rdt_submit_gauge(const char *cgroup, const char *type,
   vl.values_len = 1;
 
   sstrncpy(vl.plugin, RDT_PLUGIN, sizeof(vl.plugin));
-  snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s", cgroup);
+  ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s", cgroup);
   sstrncpy(vl.type, type, sizeof(vl.type));
   if (type_instance)
     sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
@@ -144,8 +144,8 @@ static void rdt_dump_cgroups(void) {
 
     memset(cores, 0, sizeof(cores));
     for (size_t j = 0; j < cgroup->num_cores; j++) {
-      snprintf(cores + strlen(cores), sizeof(cores) - strlen(cores) - 1, " %d",
-               cgroup->cores[j]);
+      ssnprintf(cores + strlen(cores), sizeof(cores) - strlen(cores) - 1, " %d",
+                cgroup->cores[j]);
     }
 
     DEBUG(RDT_PLUGIN ":  group[%zu]:", i);
@@ -171,8 +171,8 @@ static void rdt_dump_ngroups(void) {
   for (size_t i = 0; i < g_rdt->num_ngroups; i++) {
     memset(names, 0, sizeof(names));
     for (size_t j = 0; j < g_rdt->ngroups[i].num_names; j++)
-      snprintf(names + strlen(names), sizeof(names) - strlen(names) - 1, " %s",
-               g_rdt->ngroups[i].names[j]);
+      ssnprintf(names + strlen(names), sizeof(names) - strlen(names) - 1, " %s",
+                g_rdt->ngroups[i].names[j]);
 
     DEBUG(RDT_PLUGIN ":  group[%d]:", (int)i);
     DEBUG(RDT_PLUGIN ":    description: %s", g_rdt->ngroups[i].desc);
@@ -249,8 +249,8 @@ static void rdt_dump_pids_data(void) {
     for (size_t j = 0; j < g_rdt->ngroups[i].num_names; ++j) {
       pids_list_t *list = g_rdt->ngroups[i].proc_pids[j]->curr;
       for (size_t k = 0; k < list->size; k++)
-        snprintf(pids + strlen(pids), sizeof(pids) - strlen(pids) - 1, " %u",
-                 list->pids[k]);
+        ssnprintf(pids + strlen(pids), sizeof(pids) - strlen(pids) - 1, " %u",
+                  list->pids[k]);
     }
     DEBUG(RDT_PLUGIN ":  [%s] %s", g_rdt->ngroups[i].desc, pids);
   }
@@ -325,8 +325,8 @@ static int strlisttoarray(char *str_list, char ***names, size_t *names_num) {
       continue;
 
     if ((isdupstr((const char **)*names, *names_num, token))) {
-      ERROR(RDT_PLUGIN ": Duplicated process name \'%s\' in group \'%s\'",
-            token, str_list);
+      ERROR(RDT_PLUGIN ": Duplicated process name \'%s\'", token);
+
       return -EINVAL;
     } else {
       if (0 != strarray_add(names, names_num, token)) {
@@ -851,9 +851,9 @@ static void rdt_init_pids_monitoring() {
     }
 
     /* update global proc_pids table */
-    proc_pids_t **proc_pids = realloc(g_rdt->proc_pids,
-                                      (g_rdt->num_proc_pids + ng->num_names) *
-                                          sizeof(*g_rdt->proc_pids));
+    proc_pids_t **proc_pids =
+        realloc(g_rdt->proc_pids, (g_rdt->num_proc_pids + ng->num_names) *
+                                      sizeof(*g_rdt->proc_pids));
     if (NULL == proc_pids) {
       ERROR(RDT_PLUGIN ": Alloc error\n");
       continue;
@@ -922,7 +922,7 @@ static int rdt_default_cgroups(void) {
     cgroup->num_cores = 1;
     cgroup->cores[0] = i;
 
-    snprintf(desc, sizeof(desc), "%d", g_rdt->pqos_cpu->cores[i].lcore);
+    ssnprintf(desc, sizeof(desc), "%d", g_rdt->pqos_cpu->cores[i].lcore);
     cgroup->desc = strdup(desc);
     if (cgroup->desc == NULL) {
       ERROR(RDT_PLUGIN ": Error allocating core group description");
index af5672b..fee8384 100644 (file)
@@ -122,7 +122,8 @@ DEF_TEST(rdt_config_ngroups__one_process) {
       {.value.string = "proc1", .type = OCONFIG_TYPE_STRING},
   };
   oconfig_item_t config_item = {
-      .values = values, .values_num = STATIC_ARRAY_SIZE(values),
+      .values = values,
+      .values_num = STATIC_ARRAY_SIZE(values),
   };
 
   /* check */
@@ -147,7 +148,8 @@ DEF_TEST(rdt_config_ngroups__two_groups) {
       {.value.string = "proc21,proc22,proc23", .type = OCONFIG_TYPE_STRING},
   };
   oconfig_item_t config_item = {
-      .values = values, .values_num = STATIC_ARRAY_SIZE(values),
+      .values = values,
+      .values_num = STATIC_ARRAY_SIZE(values),
   };
 
   /* check */
@@ -178,7 +180,8 @@ DEF_TEST(rdt_config_ngroups__too_long_proc_name) {
       {.value.string = "_seventeen_chars_", .type = OCONFIG_TYPE_STRING},
   };
   oconfig_item_t config_item = {
-      .values = values, .values_num = STATIC_ARRAY_SIZE(values),
+      .values = values,
+      .values_num = STATIC_ARRAY_SIZE(values),
   };
 
   /* check */
@@ -200,7 +203,8 @@ DEF_TEST(rdt_config_ngroups__duplicate_proc_name_between_groups) {
       {.value.string = "proc21,proc,proc23", .type = OCONFIG_TYPE_STRING},
   };
   oconfig_item_t config_item = {
-      .values = values, .values_num = STATIC_ARRAY_SIZE(values),
+      .values = values,
+      .values_num = STATIC_ARRAY_SIZE(values),
   };
 
   /* check */
@@ -221,7 +225,8 @@ DEF_TEST(rdt_config_ngroups__duplicate_proc_name_in_group) {
       {.value.string = "proc11,proc,proc,proc14", .type = OCONFIG_TYPE_STRING},
   };
   oconfig_item_t config_item = {
-      .values = values, .values_num = STATIC_ARRAY_SIZE(values),
+      .values = values,
+      .values_num = STATIC_ARRAY_SIZE(values),
   };
 
   /* check */
@@ -244,7 +249,8 @@ DEF_TEST(rdt_config_ngroups__empty_group) {
 
   };
   oconfig_item_t config_item = {
-      .values = values, .values_num = STATIC_ARRAY_SIZE(values),
+      .values = values,
+      .values_num = STATIC_ARRAY_SIZE(values),
   };
 
   /* check */
@@ -265,7 +271,8 @@ DEF_TEST(rdt_config_ngroups__empty_proc_name) {
       {.value.string = "proc11,,proc13", .type = OCONFIG_TYPE_STRING},
   };
   oconfig_item_t config_item = {
-      .values = values, .values_num = STATIC_ARRAY_SIZE(values),
+      .values = values,
+      .values_num = STATIC_ARRAY_SIZE(values),
   };
 
   /* check */
index 0e13970..b0d9eeb 100644 (file)
@@ -82,7 +82,9 @@ static int pnif;
  * (Module-)Global variables
  */
 static const char *config_keys[] = {
-    "Interface", "IgnoreSelected", "ReportInactive",
+    "Interface",
+    "IgnoreSelected",
+    "ReportInactive",
 };
 static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
 
@@ -160,7 +162,8 @@ static void if_submit(const char *dev, const char *type, derive_t rx,
                       derive_t tx) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = rx}, {.derive = tx},
+      {.derive = rx},
+      {.derive = tx},
   };
 
   if (ignorelist_match(ignorelist, dev) != 0)
@@ -188,7 +191,7 @@ static int interface_read(void) {
 #define IFA_TX_PACKT ifi_opackets
 #define IFA_RX_ERROR ifi_ierrors
 #define IFA_TX_ERROR ifi_oerrors
-/* #endif HAVE_STRUCT_IF_DATA */
+  /* #endif HAVE_STRUCT_IF_DATA */
 
 #elif HAVE_STRUCT_NET_DEVICE_STATS
 #define IFA_DATA net_device_stats
@@ -226,7 +229,7 @@ static int interface_read(void) {
   }
 
   freeifaddrs(if_list);
-/* #endif HAVE_GETIFADDRS */
+  /* #endif HAVE_GETIFADDRS */
 
 #elif KERNEL_LINUX
   FILE *fh;
@@ -282,7 +285,7 @@ static int interface_read(void) {
   }
 
   fclose(fh);
-/* #endif KERNEL_LINUX */
+  /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKSTAT
   derive_t rx;
@@ -297,8 +300,8 @@ static int interface_read(void) {
       continue;
 
     if (unique_name)
-      snprintf(iname, sizeof(iname), "%s_%d_%s", ksp[i]->ks_module,
-               ksp[i]->ks_instance, ksp[i]->ks_name);
+      ssnprintf(iname, sizeof(iname), "%s_%d_%s", ksp[i]->ks_module,
+                ksp[i]->ks_instance, ksp[i]->ks_name);
     else
       sstrncpy(iname, ksp[i]->ks_name, sizeof(iname));
 
@@ -332,7 +335,7 @@ static int interface_read(void) {
     if ((rx != -1LL) || (tx != -1LL))
       if_submit(iname, "if_errors", rx, tx);
   }
-/* #endif HAVE_LIBKSTAT */
+    /* #endif HAVE_LIBKSTAT */
 
 #elif defined(HAVE_LIBSTATGRAB)
   sg_network_io_stats *ios;
@@ -345,7 +348,7 @@ static int interface_read(void) {
       continue;
     if_submit(ios[i].interface_name, "if_octets", ios[i].rx, ios[i].tx);
   }
-/* #endif HAVE_LIBSTATGRAB */
+    /* #endif HAVE_LIBSTATGRAB */
 
 #elif defined(HAVE_PERFSTAT)
   perfstat_id_t id;
index ab4b214..93eddaf 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -173,8 +173,8 @@ static int ipc_init(void) /* {{{ */
   pagesize_g = sysconf(_SC_PAGESIZE);
   return 0;
 }
-/* }}} */
-/* #endif KERNEL_LINUX */
+  /* }}} */
+  /* #endif KERNEL_LINUX */
 
 #elif KERNEL_AIX
 static caddr_t ipc_get_info(cid_t cid, int cmd, int version, int stsize,
index d78ffa9..db0e775 100644 (file)
@@ -111,7 +111,7 @@ static void c_ipmi_error(c_ipmi_instance_t *st, const char *func, int status) {
   }
 
   if (errbuf[0] == 0) {
-    snprintf(errbuf, sizeof(errbuf), "Unknown error %#x", status);
+    ssnprintf(errbuf, sizeof(errbuf), "Unknown error %#x", status);
   }
   errbuf[sizeof(errbuf) - 1] = '\0';
 
@@ -201,8 +201,8 @@ static void sensor_read_handler(ipmi_sensor_t *sensor, int err,
           sstrncpy(n.type_instance, list_item->type_instance,
                    sizeof(n.type_instance));
           sstrncpy(n.type, list_item->sensor_type, sizeof(n.type));
-          snprintf(n.message, sizeof(n.message), "sensor %s not present",
-                   list_item->sensor_name);
+          ssnprintf(n.message, sizeof(n.message), "sensor %s not present",
+                    list_item->sensor_name);
 
           plugin_dispatch_notification(&n);
         }
@@ -254,8 +254,8 @@ static void sensor_read_handler(ipmi_sensor_t *sensor, int err,
       sstrncpy(n.type_instance, list_item->type_instance,
                sizeof(n.type_instance));
       sstrncpy(n.type, list_item->sensor_type, sizeof(n.type));
-      snprintf(n.message, sizeof(n.message), "sensor %s present",
-               list_item->sensor_name);
+      ssnprintf(n.message, sizeof(n.message), "sensor %s present",
+                list_item->sensor_name);
 
       plugin_dispatch_notification(&n);
     }
@@ -313,7 +313,8 @@ static void sensor_get_name(ipmi_sensor_t *sensor, char *buffer, int buf_len) {
   temp[sizeof(temp) - 1] = '\0';
 
   if (entity_id_string != NULL && strlen(temp))
-    snprintf(sensor_name, sizeof(sensor_name), "%s %s", temp, entity_id_string);
+    ssnprintf(sensor_name, sizeof(sensor_name), "%s %s", temp,
+              entity_id_string);
   else if (entity_id_string != NULL)
     sstrncpy(sensor_name, entity_id_string, sizeof(sensor_name));
   else
@@ -338,8 +339,8 @@ static void sensor_get_name(ipmi_sensor_t *sensor, char *buffer, int buf_len) {
       sensor_id_ptr = strstr(temp, "(");
       if (sensor_id_ptr != NULL) {
         /* `sensor_id_ptr' now points to "(123)". */
-        snprintf(sensor_name, sizeof(sensor_name), "%s %s", sensor_name_ptr,
-                 sensor_id_ptr);
+        ssnprintf(sensor_name, sizeof(sensor_name), "%s %s", sensor_name_ptr,
+                  sensor_id_ptr);
       }
       /* else: don't touch sensor_name. */
     }
@@ -493,8 +494,8 @@ static int sensor_list_add(c_ipmi_instance_t *st, ipmi_sensor_t *sensor) {
   /* if sensor provides the percentage value, use "percent" collectd type
      and add the `percent` to the type instance of the reported value */
   if (ipmi_sensor_get_percentage(sensor)) {
-    snprintf(list_item->type_instance, sizeof(list_item->type_instance),
-             "percent-%s", sensor_name_ptr);
+    ssnprintf(list_item->type_instance, sizeof(list_item->type_instance),
+              "percent-%s", sensor_name_ptr);
     type = "percent";
   } else {
     /* use type instance as a name of the sensor */
@@ -514,8 +515,8 @@ static int sensor_list_add(c_ipmi_instance_t *st, ipmi_sensor_t *sensor) {
     sstrncpy(n.type_instance, list_item->type_instance,
              sizeof(n.type_instance));
     sstrncpy(n.type, list_item->sensor_type, sizeof(n.type));
-    snprintf(n.message, sizeof(n.message), "sensor %s added",
-             list_item->sensor_name);
+    ssnprintf(n.message, sizeof(n.message), "sensor %s added",
+              list_item->sensor_name);
 
     plugin_dispatch_notification(&n);
   }
@@ -561,8 +562,8 @@ static int sensor_list_remove(c_ipmi_instance_t *st, ipmi_sensor_t *sensor) {
     sstrncpy(n.type_instance, list_item->type_instance,
              sizeof(n.type_instance));
     sstrncpy(n.type, list_item->sensor_type, sizeof(n.type));
-    snprintf(n.message, sizeof(n.message), "sensor %s removed",
-             list_item->sensor_name);
+    ssnprintf(n.message, sizeof(n.message), "sensor %s removed",
+              list_item->sensor_name);
 
     plugin_dispatch_notification(&n);
   }
@@ -674,13 +675,13 @@ static int sensor_threshold_event_handler(
       ipmi_get_reading_name(event_type, sensor_type, offset);
   sensor_get_name(sensor, n.type_instance, sizeof(n.type_instance));
   if (value_present != IPMI_NO_VALUES_PRESENT)
-    snprintf(n.message, sizeof(n.message),
-             "sensor %s received event: %s, value is %f", n.type_instance,
-             event_state, value);
+    ssnprintf(n.message, sizeof(n.message),
+              "sensor %s received event: %s, value is %f", n.type_instance,
+              event_state, value);
   else
-    snprintf(n.message, sizeof(n.message),
-             "sensor %s received event: %s, value not provided",
-             n.type_instance, event_state);
+    ssnprintf(n.message, sizeof(n.message),
+              "sensor %s received event: %s, value not provided",
+              n.type_instance, event_state);
 
   DEBUG("Threshold event received for sensor %s", n.type_instance);
 
@@ -699,7 +700,7 @@ static int sensor_threshold_event_handler(
   /* both values present, so fall-through to add raw value too */
   case IPMI_RAW_VALUE_PRESENT: {
     char buf[DATA_MAX_NAME_LEN] = {0};
-    snprintf(buf, sizeof(buf), "0x%2.2x", raw_value);
+    ssnprintf(buf, sizeof(buf), "0x%2.2x", raw_value);
     plugin_notification_meta_add_string(&n, "raw", buf);
   } break;
   default:
@@ -741,8 +742,8 @@ static int sensor_discrete_event_handler(ipmi_sensor_t *sensor,
   const char *event_state =
       ipmi_get_reading_name(event_type, sensor_type, offset);
   sensor_get_name(sensor, n.type_instance, sizeof(n.type_instance));
-  snprintf(n.message, sizeof(n.message), "sensor %s received event: %s",
-           n.type_instance, event_state);
+  ssnprintf(n.message, sizeof(n.message), "sensor %s received event: %s",
+            n.type_instance, event_state);
 
   DEBUG("Discrete event received for sensor %s", n.type_instance);
 
@@ -1253,7 +1254,7 @@ static int c_ipmi_init(void) {
     /* The `st->name` is used as "domain name" for ipmi_open_domain().
      * That value should be unique, so we do plugin_register_complex_read()
      * at first as it checks the uniqueness. */
-    snprintf(callback_name, sizeof(callback_name), "ipmi/%s", st->name);
+    ssnprintf(callback_name, sizeof(callback_name), "ipmi/%s", st->name);
 
     user_data_t ud = {
         .data = st,
index e1d83df..ea2d240 100644 (file)
@@ -221,8 +221,8 @@ static int submit6_match(const struct ip6t_entry_match *match,
 
   sstrncpy(vl.plugin, "ip6tables", sizeof(vl.plugin));
 
-  status = snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
-                    chain->table, chain->chain);
+  status = ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
+                     chain->table, chain->chain);
   if ((status < 1) || ((unsigned int)status >= sizeof(vl.plugin_instance)))
     return 0;
 
@@ -230,8 +230,8 @@ static int submit6_match(const struct ip6t_entry_match *match,
     sstrncpy(vl.type_instance, chain->name, sizeof(vl.type_instance));
   } else {
     if (chain->rule_type == RTYPE_NUM)
-      snprintf(vl.type_instance, sizeof(vl.type_instance), "%i",
-               chain->rule.num);
+      ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%i",
+                chain->rule.num);
     else
       sstrncpy(vl.type_instance, (char *)match->data, sizeof(vl.type_instance));
   }
@@ -269,8 +269,8 @@ static int submit_match(const struct ipt_entry_match *match,
 
   sstrncpy(vl.plugin, "iptables", sizeof(vl.plugin));
 
-  status = snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
-                    chain->table, chain->chain);
+  status = ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
+                     chain->table, chain->chain);
   if ((status < 1) || ((unsigned int)status >= sizeof(vl.plugin_instance)))
     return 0;
 
@@ -278,8 +278,8 @@ static int submit_match(const struct ipt_entry_match *match,
     sstrncpy(vl.type_instance, chain->name, sizeof(vl.type_instance));
   } else {
     if (chain->rule_type == RTYPE_NUM)
-      snprintf(vl.type_instance, sizeof(vl.type_instance), "%i",
-               chain->rule.num);
+      ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%i",
+                chain->rule.num);
     else
       sstrncpy(vl.type_instance, (char *)match->data, sizeof(vl.type_instance));
   }
index 0259df8..0dcc8b3 100644 (file)
@@ -207,7 +207,8 @@ static void cipvs_submit_connections(const char *pi, const char *ti,
 static void cipvs_submit_if(const char *pi, const char *t, const char *ti,
                             derive_t rx, derive_t tx) {
   value_t values[] = {
-      {.derive = rx}, {.derive = tx},
+      {.derive = rx},
+      {.derive = tx},
   };
   value_list_t vl = VALUE_LIST_INIT;
 
index cf301c6..4da73bb 100644 (file)
@@ -1306,7 +1306,8 @@ static jint JNICALL cjni_api_register_read(JNIEnv *jvm_env, /* {{{ */
       /* group = */ NULL, cbi->name, cjni_read,
       /* interval = */ 0,
       &(user_data_t){
-          .data = cbi, .free_func = cjni_callback_info_destroy,
+          .data = cbi,
+          .free_func = cjni_callback_info_destroy,
       });
 
   (*jvm_env)->DeleteLocalRef(jvm_env, o_read);
@@ -1325,11 +1326,11 @@ static jint JNICALL cjni_api_register_write(JNIEnv *jvm_env, /* {{{ */
 
   DEBUG("java plugin: Registering new write callback: %s", cbi->name);
 
-  plugin_register_write(
-      cbi->name, cjni_write,
-      &(user_data_t){
-          .data = cbi, .free_func = cjni_callback_info_destroy,
-      });
+  plugin_register_write(cbi->name, cjni_write,
+                        &(user_data_t){
+                            .data = cbi,
+                            .free_func = cjni_callback_info_destroy,
+                        });
 
   (*jvm_env)->DeleteLocalRef(jvm_env, o_write);
 
@@ -1347,11 +1348,11 @@ static jint JNICALL cjni_api_register_flush(JNIEnv *jvm_env, /* {{{ */
 
   DEBUG("java plugin: Registering new flush callback: %s", cbi->name);
 
-  plugin_register_flush(
-      cbi->name, cjni_flush,
-      &(user_data_t){
-          .data = cbi, .free_func = cjni_callback_info_destroy,
-      });
+  plugin_register_flush(cbi->name, cjni_flush,
+                        &(user_data_t){
+                            .data = cbi,
+                            .free_func = cjni_callback_info_destroy,
+                        });
 
   (*jvm_env)->DeleteLocalRef(jvm_env, o_flush);
 
@@ -1377,7 +1378,8 @@ static jint JNICALL cjni_api_register_log(JNIEnv *jvm_env, /* {{{ */
 
   plugin_register_log(cbi->name, cjni_log,
                       &(user_data_t){
-                          .data = cbi, .free_func = cjni_callback_info_destroy,
+                          .data = cbi,
+                          .free_func = cjni_callback_info_destroy,
                       });
 
   (*jvm_env)->DeleteLocalRef(jvm_env, o_log);
@@ -1397,11 +1399,11 @@ static jint JNICALL cjni_api_register_notification(JNIEnv *jvm_env, /* {{{ */
 
   DEBUG("java plugin: Registering new notification callback: %s", cbi->name);
 
-  plugin_register_notification(
-      cbi->name, cjni_notification,
-      &(user_data_t){
-          .data = cbi, .free_func = cjni_callback_info_destroy,
-      });
+  plugin_register_notification(cbi->name, cjni_notification,
+                               &(user_data_t){
+                                   .data = cbi,
+                                   .free_func = cjni_callback_info_destroy,
+                               });
 
   (*jvm_env)->DeleteLocalRef(jvm_env, o_notification);
 
@@ -1543,16 +1545,19 @@ static JNINativeMethod jni_api_functions[] = /* {{{ */
          "(Ljava/lang/String;Lorg/collectd/api/CollectdLogInterface;)I",
          cjni_api_register_log},
 
-        {"registerNotification", "(Ljava/lang/String;Lorg/collectd/api/"
-                                 "CollectdNotificationInterface;)I",
+        {"registerNotification",
+         "(Ljava/lang/String;Lorg/collectd/api/"
+         "CollectdNotificationInterface;)I",
          cjni_api_register_notification},
 
-        {"registerMatch", "(Ljava/lang/String;Lorg/collectd/api/"
-                          "CollectdMatchFactoryInterface;)I",
+        {"registerMatch",
+         "(Ljava/lang/String;Lorg/collectd/api/"
+         "CollectdMatchFactoryInterface;)I",
          cjni_api_register_match},
 
-        {"registerTarget", "(Ljava/lang/String;Lorg/collectd/api/"
-                           "CollectdTargetFactoryInterface;)I",
+        {"registerTarget",
+         "(Ljava/lang/String;Lorg/collectd/api/"
+         "CollectdTargetFactoryInterface;)I",
          cjni_api_register_target},
 
         {"log", "(ILjava/lang/String;)V", cjni_api_log},
@@ -2071,7 +2076,7 @@ static int cjni_config_load_plugin(oconfig_item_t *ci) /* {{{ */
     class->object = NULL;
   if (class->object == NULL) {
     ERROR("java plugin: cjni_config_load_plugin: "
-          "Could create a new `%s' object.",
+          "Could not create a new `%s' object.",
           class->name);
     cjni_thread_detach();
     free(class->name);
index 69f9764..a8bbe2f 100644 (file)
@@ -147,7 +147,7 @@ static char *sstrerror(int errnum, char *buf, size_t buflen) {
 
 #if !HAVE_STRERROR_R
   snprintf(buf, buflen, "Error #%i; strerror_r is not available.", errnum);
-/* #endif !HAVE_STRERROR_R */
+  /* #endif !HAVE_STRERROR_R */
 
 #elif STRERROR_R_CHAR_P
   {
@@ -157,17 +157,19 @@ static char *sstrerror(int errnum, char *buf, size_t buflen) {
       if ((temp != NULL) && (temp != buf) && (temp[0] != 0))
         strncpy(buf, temp, buflen);
       else
-        strncpy(buf, "strerror_r did not return "
-                     "an error message",
+        strncpy(buf,
+                "strerror_r did not return "
+                "an error message",
                 buflen);
     }
   }
-/* #endif STRERROR_R_CHAR_P */
+    /* #endif STRERROR_R_CHAR_P */
 
 #else
   if (strerror_r(errnum, buf, buflen) != 0) {
-    snprintf(buf, buflen, "Error #%i; "
-                          "Additionally, strerror_r failed.",
+    snprintf(buf, buflen,
+             "Error #%i; "
+             "Additionally, strerror_r failed.",
              errnum);
   }
 #endif /* STRERROR_R_CHAR_P */
index 4c610bb..73ef024 100644 (file)
@@ -293,7 +293,8 @@ static double ntohd(double val) /* {{{ */
 static int parse_values(void *payload, size_t payload_size,
                         lcc_value_list_t *state) {
   buffer_t *b = &(buffer_t){
-      .data = payload, .len = payload_size,
+      .data = payload,
+      .len = payload_size,
   };
 
   uint16_t n;
@@ -401,7 +402,8 @@ static int parse_sign_sha256(void *signature, size_t signature_len,
   }
 
   buffer_t *b = &(buffer_t){
-      .data = signature, .len = signature_len,
+      .data = signature,
+      .len = signature_len,
   };
 
   uint8_t hash[32];
@@ -459,7 +461,8 @@ static int parse_encrypt_aes256(void *data, size_t data_size,
   }
 
   buffer_t *b = &(buffer_t){
-      .data = data, .len = data_size,
+      .data = data,
+      .len = data_size,
   };
 
   uint16_t username_len;
@@ -508,7 +511,8 @@ static int parse_encrypt_aes256(void *data, size_t data_size,
 static int network_parse(void *data, size_t data_size, lcc_security_level_t sl,
                          lcc_network_parse_options_t const *opts) {
   buffer_t *b = &(buffer_t){
-      .data = data, .len = data_size,
+      .data = data,
+      .len = data_size,
   };
 
   lcc_value_list_t state = {0};
index a638642..519a2c5 100644 (file)
@@ -245,16 +245,17 @@ static int test_network_parse() {
     uint8_t buffer[LCC_NETWORK_BUFFER_SIZE_DEFAULT];
     size_t buffer_size = sizeof(buffer);
     if (decode_string(raw_packet_data[i], buffer, &buffer_size)) {
-      fprintf(stderr, "lcc_network_parse(raw_packet_data[%" PRIsz "]):"
-                      " decoding string failed\n",
+      fprintf(stderr,
+              "lcc_network_parse(raw_packet_data[%" PRIsz "]):"
+              " decoding string failed\n",
               i);
       return -1;
     }
 
-    int status =
-        lcc_network_parse(buffer, buffer_size, (lcc_network_parse_options_t){
-                                                   .writer = nop_writer,
-                                               });
+    int status = lcc_network_parse(buffer, buffer_size,
+                                   (lcc_network_parse_options_t){
+                                       .writer = nop_writer,
+                                   });
     if (status != 0) {
       fprintf(stderr,
               "lcc_network_parse(raw_packet_data[%" PRIsz "]) = %d, want 0\n",
@@ -466,7 +467,8 @@ static int test_decrypt_aes256() {
 
   int status = decrypt_aes256(
       &(buffer_t){
-          .data = ciphertext, .len = ciphertext_len,
+          .data = ciphertext,
+          .len = ciphertext_len,
       },
       iv, iv_len, "admin");
   if (status != 0) {
index 25b81ab..68edce8 100644 (file)
@@ -1,17 +1,15 @@
 #ifndef AUX_TYPES_H
 #define AUX_TYPES_H 1
 
-struct statement_list_s
-{
-       oconfig_item_t *statement;
-       int             statement_num;
+struct statement_list_s {
+  oconfig_item_t *statement;
+  int statement_num;
 };
 typedef struct statement_list_s statement_list_t;
 
-struct argument_list_s
-{
-       oconfig_value_t *argument;
-       int              argument_num;
+struct argument_list_s {
+  oconfig_value_t *argument;
+  int argument_num;
 };
 typedef struct argument_list_s argument_list_t;
 
index da7fe58..a94ee96 100644 (file)
@@ -61,7 +61,7 @@ static const char *config_keys[] = {"ReportRelative"};
 static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
 
 static int load_config(const char *key, const char *value) {
-  if (strcasecmp(key, "ReportRelative") == 0)
+  if (strcasecmp(key, "ReportRelative") == 0) {
 #ifdef _SC_NPROCESSORS_ONLN
     report_relative_load = IS_TRUE(value);
 #else
@@ -69,6 +69,8 @@ static int load_config(const char *key, const char *value) {
             "is not available, because I can't determine the "
             "number of CPUS on this system. Sorry.");
 #endif
+    return 0;
+  }
   return -1;
 }
 static void load_submit(gauge_t snum, gauge_t mnum, gauge_t lnum) {
@@ -89,7 +91,9 @@ static void load_submit(gauge_t snum, gauge_t mnum, gauge_t lnum) {
 
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.gauge = snum}, {.gauge = mnum}, {.gauge = lnum},
+      {.gauge = snum},
+      {.gauge = mnum},
+      {.gauge = lnum},
   };
 
   vl.values = values;
@@ -114,7 +118,7 @@ static int load_read(void) {
   else {
     WARNING("load: getloadavg failed: %s", STRERRNO);
   }
-/* #endif HAVE_GETLOADAVG */
+    /* #endif HAVE_GETLOADAVG */
 
 #elif defined(KERNEL_LINUX)
   gauge_t snum, mnum, lnum;
@@ -149,7 +153,7 @@ static int load_read(void) {
   lnum = atof(fields[2]);
 
   load_submit(snum, mnum, lnum);
-/* #endif KERNEL_LINUX */
+  /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBSTATGRAB
   gauge_t snum, mnum, lnum;
@@ -162,7 +166,7 @@ static int load_read(void) {
   mnum = ls->min5;
   lnum = ls->min15;
   load_submit(snum, mnum, lnum);
-/* #endif HAVE_LIBSTATGRAB */
+  /* #endif HAVE_LIBSTATGRAB */
 
 #elif HAVE_PERFSTAT
   gauge_t snum, mnum, lnum;
@@ -178,7 +182,7 @@ static int load_read(void) {
   mnum = (float)cputotal.loadavg[1] / (float)(1 << SBITS);
   lnum = (float)cputotal.loadavg[2] / (float)(1 << SBITS);
   load_submit(snum, mnum, lnum);
-/* #endif HAVE_PERFSTAT */
+  /* #endif HAVE_PERFSTAT */
 
 #else
 #error "No applicable input method."
index 3a25319..ef75052 100644 (file)
@@ -52,8 +52,8 @@ static int logfile_config(const char *key, const char *value) {
     log_level = parse_log_severity(value);
     if (log_level < 0) {
       log_level = LOG_INFO;
-      ERROR("logfile: invalid loglevel [%s] defaulting to 'info'", value);
-      return 1;
+      WARNING("logfile: invalid loglevel [%s] defaulting to 'info'", value);
+      return 0;
     }
   } else if (0 == strcasecmp(key, "File")) {
     sfree(log_file);
index dc3739b..1c8685e 100644 (file)
@@ -224,10 +224,10 @@ static int lpar_read(void) {
     if (pool_busy_cpus < 0.0)
       pool_busy_cpus = 0.0;
 
-    snprintf(typinst, sizeof(typinst), "pool-%X-busy", lparstats.pool_id);
+    ssnprintf(typinst, sizeof(typinst), "pool-%X-busy", lparstats.pool_id);
     lpar_submit(typinst, pool_busy_cpus);
 
-    snprintf(typinst, sizeof(typinst), "pool-%X-idle", lparstats.pool_id);
+    ssnprintf(typinst, sizeof(typinst), "pool-%X-idle", lparstats.pool_id);
     lpar_submit(typinst, pool_idle_cpus);
   }
 
index 9a1ceed..3f48a55 100644 (file)
--- a/src/lua.c
+++ b/src/lua.c
@@ -278,7 +278,7 @@ static int lua_cb_register_generic(lua_State *L, int type) /* {{{ */
   char subname[DATA_MAX_NAME_LEN];
   if (!lua_isfunction(L, 1) && lua_isstring(L, 1)) {
     const char *fname = lua_tostring(L, 1);
-    snprintf(subname, sizeof(subname), "%s()", fname);
+    ssnprintf(subname, sizeof(subname), "%s()", fname);
 
     lua_getglobal(L, fname); // Push function into stack
     lua_remove(L, 1);        // Remove string from stack
@@ -288,7 +288,7 @@ static int lua_cb_register_generic(lua_State *L, int type) /* {{{ */
   } else {
     lua_getfield(L, LUA_REGISTRYINDEX, "collectd:callback_num");
     int tmp = lua_tointeger(L, -1);
-    snprintf(subname, sizeof(subname), "callback_%d", tmp);
+    ssnprintf(subname, sizeof(subname), "callback_%d", tmp);
     lua_pop(L, 1); // Remove old value from stack
     lua_pushinteger(L, tmp + 1);
     lua_setfield(L, LUA_REGISTRYINDEX, "collectd:callback_num"); // pops value
@@ -298,8 +298,8 @@ static int lua_cb_register_generic(lua_State *L, int type) /* {{{ */
 
   lua_getfield(L, LUA_REGISTRYINDEX, "collectd:script_path");
   char function_name[DATA_MAX_NAME_LEN];
-  snprintf(function_name, sizeof(function_name), "lua/%s/%s",
-           lua_tostring(L, -1), subname);
+  ssnprintf(function_name, sizeof(function_name), "lua/%s/%s",
+            lua_tostring(L, -1), subname);
   lua_pop(L, 1);
 
   int callback_id = clua_store_callback(L, 1);
@@ -322,14 +322,14 @@ static int lua_cb_register_generic(lua_State *L, int type) /* {{{ */
   pthread_mutex_init(&cb->lock, NULL);
 
   if (PLUGIN_READ == type) {
-    int status =
-        plugin_register_complex_read(/* group = */ "lua",
-                                     /* name      = */ function_name,
-                                     /* callback  = */ clua_read,
-                                     /* interval  = */ 0,
-                                     &(user_data_t){
-                                         .data = cb, .free_func = lua_cb_free,
-                                     });
+    int status = plugin_register_complex_read(/* group = */ "lua",
+                                              /* name      = */ function_name,
+                                              /* callback  = */ clua_read,
+                                              /* interval  = */ 0,
+                                              &(user_data_t){
+                                                  .data = cb,
+                                                  .free_func = lua_cb_free,
+                                              });
 
     if (status != 0)
       return luaL_error(L, "%s", "plugin_register_complex_read failed");
@@ -338,7 +338,8 @@ static int lua_cb_register_generic(lua_State *L, int type) /* {{{ */
     int status = plugin_register_write(/* name = */ function_name,
                                        /* callback  = */ clua_write,
                                        &(user_data_t){
-                                           .data = cb, .free_func = lua_cb_free,
+                                           .data = cb,
+                                           .free_func = lua_cb_free,
                                        });
 
     if (status != 0)
@@ -530,7 +531,7 @@ static int lua_config_script(const oconfig_item_t *ci) /* {{{ */
   if (base_path[0] == '\0')
     sstrncpy(abs_path, rel_path, sizeof(abs_path));
   else
-    snprintf(abs_path, sizeof(abs_path), "%s/%s", base_path, rel_path);
+    ssnprintf(abs_path, sizeof(abs_path), "%s/%s", base_path, rel_path);
 
   DEBUG("Lua plugin: abs_path = \"%s\";", abs_path);
 
diff --git a/src/lvm.c b/src/lvm.c
deleted file mode 100644 (file)
index c30489c..0000000
--- a/src/lvm.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/**
- * collectd - src/lvm.c
- * Copyright (C) 2013       Chad Malfait
- * Copyright (C) 2014       Carnegie Mellon University
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; only version 2 of the License is applicable.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Chad Malfait <malfaitc at yahoo.com>
- *   Benjamin Gilbert <bgilbert at backtick.net>
- **/
-
-#include "collectd.h"
-
-#include "plugin.h"
-#include "utils/common/common.h"
-
-#include <lvm2app.h>
-
-#ifdef HAVE_SYS_CAPABILITY_H
-#include <sys/capability.h>
-#endif /* HAVE_SYS_CAPABILITY_H */
-
-#define NO_VALUE UINT64_MAX
-#define PERCENT_SCALE_FACTOR 1e-8
-
-static uint64_t get_lv_property_int(lv_t lv, char const *property) {
-  lvm_property_value_t v;
-
-  v = lvm_lv_get_property(lv, property);
-  if (!v.is_valid || !v.is_integer)
-    return NO_VALUE;
-  /* May be NO_VALUE if @property does not apply to this LV */
-  return v.value.integer;
-}
-
-static char const *get_lv_property_string(lv_t lv, char const *property) {
-  lvm_property_value_t v;
-
-  v = lvm_lv_get_property(lv, property);
-  if (!v.is_valid || !v.is_string)
-    return NULL;
-  return v.value.string;
-}
-
-static void lvm_submit(char const *plugin_instance, char const *type_instance,
-                       uint64_t ivalue) {
-  value_list_t vl = VALUE_LIST_INIT;
-
-  vl.values = &(value_t){.gauge = (gauge_t)ivalue};
-  vl.values_len = 1;
-
-  sstrncpy(vl.plugin, "lvm", sizeof(vl.plugin));
-  sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance));
-  sstrncpy(vl.type, "df_complex", sizeof(vl.type));
-  sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
-
-  plugin_dispatch_values(&vl);
-}
-
-static void report_lv_utilization(lv_t lv, char const *vg_name,
-                                  char const *lv_name, uint64_t lv_size,
-                                  char const *used_percent_property) {
-  uint64_t used_percent_unscaled;
-  uint64_t used_bytes;
-  char plugin_instance[DATA_MAX_NAME_LEN];
-
-  used_percent_unscaled = get_lv_property_int(lv, used_percent_property);
-  if (used_percent_unscaled == NO_VALUE)
-    return;
-  used_bytes = lv_size * (used_percent_unscaled * PERCENT_SCALE_FACTOR);
-
-  snprintf(plugin_instance, sizeof(plugin_instance), "%s-%s", vg_name, lv_name);
-  lvm_submit(plugin_instance, "used", used_bytes);
-  lvm_submit(plugin_instance, "free", lv_size - used_bytes);
-}
-
-static void report_thin_pool_utilization(lv_t lv, char const *vg_name,
-                                         uint64_t lv_size) {
-  char const *data_lv;
-  char const *metadata_lv;
-  uint64_t metadata_size;
-
-  data_lv = get_lv_property_string(lv, "data_lv");
-  metadata_lv = get_lv_property_string(lv, "metadata_lv");
-  metadata_size = get_lv_property_int(lv, "lv_metadata_size");
-  if (data_lv == NULL || metadata_lv == NULL || metadata_size == NO_VALUE)
-    return;
-
-  report_lv_utilization(lv, vg_name, data_lv, lv_size, "data_percent");
-  report_lv_utilization(lv, vg_name, metadata_lv, metadata_size,
-                        "metadata_percent");
-}
-
-static void vg_read(vg_t vg, char const *vg_name) {
-  struct dm_list *lvs;
-  struct lvm_lv_list *lvl;
-  char const *name;
-  char const *attrs;
-  uint64_t size;
-
-  lvm_submit(vg_name, "free", lvm_vg_get_free_size(vg));
-
-  lvs = lvm_vg_list_lvs(vg);
-  if (!lvs) {
-    /* no VGs are defined, which is not an error per se */
-    return;
-  }
-
-  dm_list_iterate_items(lvl, lvs) {
-    name = lvm_lv_get_name(lvl->lv);
-    attrs = get_lv_property_string(lvl->lv, "lv_attr");
-    size = lvm_lv_get_size(lvl->lv);
-    if (name == NULL || attrs == NULL || size == NO_VALUE)
-      continue;
-
-    /* Condition on volume type.  We want the reported sizes in the
-       volume group to sum to the size of the volume group, so we ignore
-       virtual volumes.  */
-    switch (attrs[0]) {
-    case 's':
-    case 'S':
-      /* Snapshot.  Also report used/free space. */
-      report_lv_utilization(lvl->lv, vg_name, name, size, "data_percent");
-      break;
-    case 't':
-      /* Thin pool virtual volume.  We report the underlying data
-         and metadata volumes, not this one.  Report used/free
-         space, then ignore. */
-      report_thin_pool_utilization(lvl->lv, vg_name, size);
-      continue;
-    case 'v':
-      /* Virtual volume.  Ignore. */
-      continue;
-    case 'V':
-      /* Thin volume or thin snapshot.  Ignore. */
-      continue;
-    }
-    lvm_submit(vg_name, name, size);
-  }
-}
-
-static int lvm_read(void) {
-  lvm_t lvm;
-  struct dm_list *vg_names;
-  struct lvm_str_list *name_list;
-
-  lvm = lvm_init(NULL);
-  if (!lvm) {
-    ERROR("lvm plugin: lvm_init failed.");
-    return -1;
-  }
-
-  vg_names = lvm_list_vg_names(lvm);
-  if (!vg_names) {
-    ERROR("lvm plugin lvm_list_vg_name failed %s", lvm_errmsg(lvm));
-    lvm_quit(lvm);
-    return -1;
-  }
-
-  dm_list_iterate_items(name_list, vg_names) {
-    vg_t vg;
-
-    vg = lvm_vg_open(lvm, name_list->str, "r", 0);
-    if (!vg) {
-      ERROR("lvm plugin: lvm_vg_open (%s) failed: %s", name_list->str,
-            lvm_errmsg(lvm));
-      continue;
-    }
-
-    vg_read(vg, name_list->str);
-    lvm_vg_close(vg);
-  }
-
-  lvm_quit(lvm);
-  return 0;
-} /*lvm_read */
-
-static int c_lvm_init(void) {
-#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_ADMIN)
-  if (check_capability(CAP_SYS_ADMIN) != 0) {
-    if (getuid() == 0)
-      WARNING("lvm plugin: Running collectd as root, but the "
-              "CAP_SYS_ADMIN capability is missing. The plugin's read "
-              "function will probably fail. Is your init system dropping "
-              "capabilities?");
-    else
-      WARNING("lvm plugin: collectd doesn't have the CAP_SYS_ADMIN "
-              "capability. If you don't want to run collectd as root, try "
-              "running \"setcap cap_sys_admin=ep\" on the collectd binary.");
-  }
-#endif
-  return 0;
-}
-
-void module_register(void) {
-  plugin_register_init("lvm", c_lvm_init);
-  plugin_register_read("lvm", lvm_read);
-} /* void module_register */
index 85454c3..723f992 100644 (file)
@@ -534,7 +534,8 @@ static void submit_derive(const char *dev, const char *type, const char *ti1,
 static void submit_derive2(const char *dev, const char *type, const char *ti1,
                            const char *ti2, derive_t val1, derive_t val2) {
   value_t values[] = {
-      {.derive = val1}, {.derive = val2},
+      {.derive = val1},
+      {.derive = val2},
   };
 
   submit(dev, type, ti1, ti2, values, STATIC_ARRAY_SIZE(values));
index d6a5e35..3a7c7f0 100644 (file)
 #ifndef MADWIFI_H
 #define MADWIFI_H
 
-#define        IEEE80211_ADDR_LEN              6               /* size of 802.11 address */
-#define        IEEE80211_RATE_VAL              0x7f
-#define        IEEE80211_RATE_SIZE             8               /* 802.11 standard */
-#define        IEEE80211_RATE_MAXSIZE          15              /* max rates we'll handle */
-
+#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */
+#define IEEE80211_RATE_VAL 0x7f
+#define IEEE80211_RATE_SIZE 8     /* 802.11 standard */
+#define IEEE80211_RATE_MAXSIZE 15 /* max rates we'll handle */
 
 /*
  * Per/node (station) statistics available when operating as an AP.
  */
 struct ieee80211_nodestats {
-       u_int32_t ns_rx_data;           /* rx data frames */
-       u_int32_t ns_rx_mgmt;           /* rx management frames */
-       u_int32_t ns_rx_ctrl;           /* rx control frames */
-       u_int32_t ns_rx_ucast;          /* rx unicast frames */
-       u_int32_t ns_rx_mcast;          /* rx multi/broadcast frames */
-       u_int64_t ns_rx_bytes;          /* rx data count (bytes) */
-       u_int64_t ns_rx_beacons;        /* rx beacon frames */
-       u_int32_t ns_rx_proberesp;      /* rx probe response frames */
+  u_int32_t ns_rx_data;      /* rx data frames */
+  u_int32_t ns_rx_mgmt;      /* rx management frames */
+  u_int32_t ns_rx_ctrl;      /* rx control frames */
+  u_int32_t ns_rx_ucast;     /* rx unicast frames */
+  u_int32_t ns_rx_mcast;     /* rx multi/broadcast frames */
+  u_int64_t ns_rx_bytes;     /* rx data count (bytes) */
+  u_int64_t ns_rx_beacons;   /* rx beacon frames */
+  u_int32_t ns_rx_proberesp; /* rx probe response frames */
 
-       u_int32_t ns_rx_dup;            /* rx discard because it's a dup */
-       u_int32_t ns_rx_noprivacy;      /* rx w/ wep but privacy off */
-       u_int32_t ns_rx_wepfail;        /* rx wep processing failed */
-       u_int32_t ns_rx_demicfail;      /* rx demic failed */
-       u_int32_t ns_rx_decap;          /* rx decapsulation failed */
-       u_int32_t ns_rx_defrag;         /* rx defragmentation failed */
-       u_int32_t ns_rx_disassoc;       /* rx disassociation */
-       u_int32_t ns_rx_deauth;         /* rx deauthentication */
-       u_int32_t ns_rx_decryptcrc;     /* rx decrypt failed on crc */
-       u_int32_t ns_rx_unauth;         /* rx on unauthorized port */
-       u_int32_t ns_rx_unencrypted;    /* rx unecrypted w/ privacy */
+  u_int32_t ns_rx_dup;         /* rx discard because it's a dup */
+  u_int32_t ns_rx_noprivacy;   /* rx w/ wep but privacy off */
+  u_int32_t ns_rx_wepfail;     /* rx wep processing failed */
+  u_int32_t ns_rx_demicfail;   /* rx demic failed */
+  u_int32_t ns_rx_decap;       /* rx decapsulation failed */
+  u_int32_t ns_rx_defrag;      /* rx defragmentation failed */
+  u_int32_t ns_rx_disassoc;    /* rx disassociation */
+  u_int32_t ns_rx_deauth;      /* rx deauthentication */
+  u_int32_t ns_rx_decryptcrc;  /* rx decrypt failed on crc */
+  u_int32_t ns_rx_unauth;      /* rx on unauthorized port */
+  u_int32_t ns_rx_unencrypted; /* rx unecrypted w/ privacy */
 
-       u_int32_t ns_tx_data;           /* tx data frames */
-       u_int32_t ns_tx_mgmt;           /* tx management frames */
-       u_int32_t ns_tx_ucast;          /* tx unicast frames */
-       u_int32_t ns_tx_mcast;          /* tx multi/broadcast frames */
-       u_int64_t ns_tx_bytes;          /* tx data count (bytes) */
-       u_int32_t ns_tx_probereq;       /* tx probe request frames */
-       u_int32_t ns_tx_uapsd;          /* tx on uapsd queue */
+  u_int32_t ns_tx_data;     /* tx data frames */
+  u_int32_t ns_tx_mgmt;     /* tx management frames */
+  u_int32_t ns_tx_ucast;    /* tx unicast frames */
+  u_int32_t ns_tx_mcast;    /* tx multi/broadcast frames */
+  u_int64_t ns_tx_bytes;    /* tx data count (bytes) */
+  u_int32_t ns_tx_probereq; /* tx probe request frames */
+  u_int32_t ns_tx_uapsd;    /* tx on uapsd queue */
 
-       u_int32_t ns_tx_novlantag;      /* tx discard due to no tag */
-       u_int32_t ns_tx_vlanmismatch;   /* tx discard due to of bad tag */
+  u_int32_t ns_tx_novlantag;    /* tx discard due to no tag */
+  u_int32_t ns_tx_vlanmismatch; /* tx discard due to of bad tag */
 
-       u_int32_t ns_tx_eosplost;       /* uapsd EOSP retried out */
+  u_int32_t ns_tx_eosplost; /* uapsd EOSP retried out */
 
-       u_int32_t ns_ps_discard;        /* ps discard due to of age */
+  u_int32_t ns_ps_discard; /* ps discard due to of age */
 
-       u_int32_t ns_uapsd_triggers;    /* uapsd triggers */
+  u_int32_t ns_uapsd_triggers; /* uapsd triggers */
 
-       /* MIB-related state */
-       u_int32_t ns_tx_assoc;          /* [re]associations */
-       u_int32_t ns_tx_assoc_fail;     /* [re]association failures */
-       u_int32_t ns_tx_auth;           /* [re]authentications */
-       u_int32_t ns_tx_auth_fail;      /* [re]authentication failures*/
-       u_int32_t ns_tx_deauth;         /* deauthentications */
-       u_int32_t ns_tx_deauth_code;    /* last deauth reason */
-       u_int32_t ns_tx_disassoc;       /* disassociations */
-       u_int32_t ns_tx_disassoc_code;  /* last disassociation reason */
-       u_int32_t ns_psq_drops;         /* power save queue drops */
+  /* MIB-related state */
+  u_int32_t ns_tx_assoc;         /* [re]associations */
+  u_int32_t ns_tx_assoc_fail;    /* [re]association failures */
+  u_int32_t ns_tx_auth;          /* [re]authentications */
+  u_int32_t ns_tx_auth_fail;     /* [re]authentication failures*/
+  u_int32_t ns_tx_deauth;        /* deauthentications */
+  u_int32_t ns_tx_deauth_code;   /* last deauth reason */
+  u_int32_t ns_tx_disassoc;      /* disassociations */
+  u_int32_t ns_tx_disassoc_code; /* last disassociation reason */
+  u_int32_t ns_psq_drops;        /* power save queue drops */
 };
 
 /*
  * Summary statistics.
  */
 struct ieee80211_stats {
-       u_int32_t is_rx_badversion;     /* rx frame with bad version */
-       u_int32_t is_rx_tooshort;       /* rx frame too short */
-       u_int32_t is_rx_wrongbss;       /* rx from wrong bssid */
-       u_int32_t is_rx_dup;            /* rx discard due to it's a dup */
-       u_int32_t is_rx_wrongdir;       /* rx w/ wrong direction */
-       u_int32_t is_rx_mcastecho;      /* rx discard due to of mcast echo */
-       u_int32_t is_rx_notassoc;       /* rx discard due to sta !assoc */
-       u_int32_t is_rx_noprivacy;      /* rx w/ wep but privacy off */
-       u_int32_t is_rx_unencrypted;    /* rx w/o wep and privacy on */
-       u_int32_t is_rx_wepfail;        /* rx wep processing failed */
-       u_int32_t is_rx_decap;          /* rx decapsulation failed */
-       u_int32_t is_rx_mgtdiscard;     /* rx discard mgt frames */
-       u_int32_t is_rx_ctl;            /* rx discard ctrl frames */
-       u_int32_t is_rx_beacon;         /* rx beacon frames */
-       u_int32_t is_rx_rstoobig;       /* rx rate set truncated */
-       u_int32_t is_rx_elem_missing;   /* rx required element missing*/
-       u_int32_t is_rx_elem_toobig;    /* rx element too big */
-       u_int32_t is_rx_elem_toosmall;  /* rx element too small */
-       u_int32_t is_rx_elem_unknown;   /* rx element unknown */
-       u_int32_t is_rx_badchan;        /* rx frame w/ invalid chan */
-       u_int32_t is_rx_chanmismatch;   /* rx frame chan mismatch */
-       u_int32_t is_rx_nodealloc;      /* rx frame dropped */
-       u_int32_t is_rx_ssidmismatch;   /* rx frame ssid mismatch  */
-       u_int32_t is_rx_auth_unsupported;/* rx w/ unsupported auth alg */
-       u_int32_t is_rx_auth_fail;      /* rx sta auth failure */
-       u_int32_t is_rx_auth_countermeasures;/* rx auth discard due to CM */
-       u_int32_t is_rx_assoc_bss;      /* rx assoc from wrong bssid */
-       u_int32_t is_rx_assoc_notauth;  /* rx assoc w/o auth */
-       u_int32_t is_rx_assoc_capmismatch;/* rx assoc w/ cap mismatch */
-       u_int32_t is_rx_assoc_norate;   /* rx assoc w/ no rate match */
-       u_int32_t is_rx_assoc_badwpaie; /* rx assoc w/ bad WPA IE */
-       u_int32_t is_rx_deauth;         /* rx deauthentication */
-       u_int32_t is_rx_disassoc;       /* rx disassociation */
-       u_int32_t is_rx_badsubtype;     /* rx frame w/ unknown subtype*/
-       u_int32_t is_rx_nobuf;          /* rx failed for lack of buf */
-       u_int32_t is_rx_decryptcrc;     /* rx decrypt failed on crc */
-       u_int32_t is_rx_ahdemo_mgt;     /* rx discard ahdemo mgt frame*/
-       u_int32_t is_rx_bad_auth;       /* rx bad auth request */
-       u_int32_t is_rx_unauth;         /* rx on unauthorized port */
-       u_int32_t is_rx_badkeyid;       /* rx w/ incorrect keyid */
-       u_int32_t is_rx_ccmpreplay;     /* rx seq# violation (CCMP) */
-       u_int32_t is_rx_ccmpformat;     /* rx format bad (CCMP) */
-       u_int32_t is_rx_ccmpmic;        /* rx MIC check failed (CCMP) */
-       u_int32_t is_rx_tkipreplay;     /* rx seq# violation (TKIP) */
-       u_int32_t is_rx_tkipformat;     /* rx format bad (TKIP) */
-       u_int32_t is_rx_tkipmic;        /* rx MIC check failed (TKIP) */
-       u_int32_t is_rx_tkipicv;        /* rx ICV check failed (TKIP) */
-       u_int32_t is_rx_badcipher;      /* rx failed due to of key type */
-       u_int32_t is_rx_nocipherctx;    /* rx failed due to key !setup */
-       u_int32_t is_rx_acl;            /* rx discard due to of acl policy */
-       u_int32_t is_rx_ffcnt;          /* rx fast frames */
-       u_int32_t is_rx_badathtnl;      /* driver key alloc failed */
-       u_int32_t is_tx_nobuf;          /* tx failed for lack of buf */
-       u_int32_t is_tx_nonode;         /* tx failed for no node */
-       u_int32_t is_tx_unknownmgt;     /* tx of unknown mgt frame */
-       u_int32_t is_tx_badcipher;      /* tx failed due to of key type */
-       u_int32_t is_tx_nodefkey;       /* tx failed due to no defkey */
-       u_int32_t is_tx_noheadroom;     /* tx failed due to no space */
-       u_int32_t is_tx_ffokcnt;        /* tx fast frames sent success */
-       u_int32_t is_tx_fferrcnt;       /* tx fast frames sent success */
-       u_int32_t is_scan_active;       /* active scans started */
-       u_int32_t is_scan_passive;      /* passive scans started */
-       u_int32_t is_node_timeout;      /* nodes timed out inactivity */
-       u_int32_t is_crypto_nomem;      /* no memory for crypto ctx */
-       u_int32_t is_crypto_tkip;       /* tkip crypto done in s/w */
-       u_int32_t is_crypto_tkipenmic;  /* tkip en-MIC done in s/w */
-       u_int32_t is_crypto_tkipdemic;  /* tkip de-MIC done in s/w */
-       u_int32_t is_crypto_tkipcm;     /* tkip counter measures */
-       u_int32_t is_crypto_ccmp;       /* ccmp crypto done in s/w */
-       u_int32_t is_crypto_wep;        /* wep crypto done in s/w */
-       u_int32_t is_crypto_setkey_cipher;/* cipher rejected key */
-       u_int32_t is_crypto_setkey_nokey;/* no key index for setkey */
-       u_int32_t is_crypto_delkey;     /* driver key delete failed */
-       u_int32_t is_crypto_badcipher;  /* unknown cipher */
-       u_int32_t is_crypto_nocipher;   /* cipher not available */
-       u_int32_t is_crypto_attachfail; /* cipher attach failed */
-       u_int32_t is_crypto_swfallback; /* cipher fallback to s/w */
-       u_int32_t is_crypto_keyfail;    /* driver key alloc failed */
-       u_int32_t is_crypto_enmicfail;  /* en-MIC failed */
-       u_int32_t is_ibss_capmismatch;  /* merge failed-cap mismatch */
-       u_int32_t is_ibss_norate;       /* merge failed-rate mismatch */
-       u_int32_t is_ps_unassoc;        /* ps-poll for unassoc. sta */
-       u_int32_t is_ps_badaid;         /* ps-poll w/ incorrect aid */
-       u_int32_t is_ps_qempty;         /* ps-poll w/ nothing to send */
+  u_int32_t is_rx_badversion;           /* rx frame with bad version */
+  u_int32_t is_rx_tooshort;             /* rx frame too short */
+  u_int32_t is_rx_wrongbss;             /* rx from wrong bssid */
+  u_int32_t is_rx_dup;                  /* rx discard due to it's a dup */
+  u_int32_t is_rx_wrongdir;             /* rx w/ wrong direction */
+  u_int32_t is_rx_mcastecho;            /* rx discard due to of mcast echo */
+  u_int32_t is_rx_notassoc;             /* rx discard due to sta !assoc */
+  u_int32_t is_rx_noprivacy;            /* rx w/ wep but privacy off */
+  u_int32_t is_rx_unencrypted;          /* rx w/o wep and privacy on */
+  u_int32_t is_rx_wepfail;              /* rx wep processing failed */
+  u_int32_t is_rx_decap;                /* rx decapsulation failed */
+  u_int32_t is_rx_mgtdiscard;           /* rx discard mgt frames */
+  u_int32_t is_rx_ctl;                  /* rx discard ctrl frames */
+  u_int32_t is_rx_beacon;               /* rx beacon frames */
+  u_int32_t is_rx_rstoobig;             /* rx rate set truncated */
+  u_int32_t is_rx_elem_missing;         /* rx required element missing*/
+  u_int32_t is_rx_elem_toobig;          /* rx element too big */
+  u_int32_t is_rx_elem_toosmall;        /* rx element too small */
+  u_int32_t is_rx_elem_unknown;         /* rx element unknown */
+  u_int32_t is_rx_badchan;              /* rx frame w/ invalid chan */
+  u_int32_t is_rx_chanmismatch;         /* rx frame chan mismatch */
+  u_int32_t is_rx_nodealloc;            /* rx frame dropped */
+  u_int32_t is_rx_ssidmismatch;         /* rx frame ssid mismatch  */
+  u_int32_t is_rx_auth_unsupported;     /* rx w/ unsupported auth alg */
+  u_int32_t is_rx_auth_fail;            /* rx sta auth failure */
+  u_int32_t is_rx_auth_countermeasures; /* rx auth discard due to CM */
+  u_int32_t is_rx_assoc_bss;            /* rx assoc from wrong bssid */
+  u_int32_t is_rx_assoc_notauth;        /* rx assoc w/o auth */
+  u_int32_t is_rx_assoc_capmismatch;    /* rx assoc w/ cap mismatch */
+  u_int32_t is_rx_assoc_norate;         /* rx assoc w/ no rate match */
+  u_int32_t is_rx_assoc_badwpaie;       /* rx assoc w/ bad WPA IE */
+  u_int32_t is_rx_deauth;               /* rx deauthentication */
+  u_int32_t is_rx_disassoc;             /* rx disassociation */
+  u_int32_t is_rx_badsubtype;           /* rx frame w/ unknown subtype*/
+  u_int32_t is_rx_nobuf;                /* rx failed for lack of buf */
+  u_int32_t is_rx_decryptcrc;           /* rx decrypt failed on crc */
+  u_int32_t is_rx_ahdemo_mgt;           /* rx discard ahdemo mgt frame*/
+  u_int32_t is_rx_bad_auth;             /* rx bad auth request */
+  u_int32_t is_rx_unauth;               /* rx on unauthorized port */
+  u_int32_t is_rx_badkeyid;             /* rx w/ incorrect keyid */
+  u_int32_t is_rx_ccmpreplay;           /* rx seq# violation (CCMP) */
+  u_int32_t is_rx_ccmpformat;           /* rx format bad (CCMP) */
+  u_int32_t is_rx_ccmpmic;              /* rx MIC check failed (CCMP) */
+  u_int32_t is_rx_tkipreplay;           /* rx seq# violation (TKIP) */
+  u_int32_t is_rx_tkipformat;           /* rx format bad (TKIP) */
+  u_int32_t is_rx_tkipmic;              /* rx MIC check failed (TKIP) */
+  u_int32_t is_rx_tkipicv;              /* rx ICV check failed (TKIP) */
+  u_int32_t is_rx_badcipher;            /* rx failed due to of key type */
+  u_int32_t is_rx_nocipherctx;          /* rx failed due to key !setup */
+  u_int32_t is_rx_acl;                  /* rx discard due to of acl policy */
+  u_int32_t is_rx_ffcnt;                /* rx fast frames */
+  u_int32_t is_rx_badathtnl;            /* driver key alloc failed */
+  u_int32_t is_tx_nobuf;                /* tx failed for lack of buf */
+  u_int32_t is_tx_nonode;               /* tx failed for no node */
+  u_int32_t is_tx_unknownmgt;           /* tx of unknown mgt frame */
+  u_int32_t is_tx_badcipher;            /* tx failed due to of key type */
+  u_int32_t is_tx_nodefkey;             /* tx failed due to no defkey */
+  u_int32_t is_tx_noheadroom;           /* tx failed due to no space */
+  u_int32_t is_tx_ffokcnt;              /* tx fast frames sent success */
+  u_int32_t is_tx_fferrcnt;             /* tx fast frames sent success */
+  u_int32_t is_scan_active;             /* active scans started */
+  u_int32_t is_scan_passive;            /* passive scans started */
+  u_int32_t is_node_timeout;            /* nodes timed out inactivity */
+  u_int32_t is_crypto_nomem;            /* no memory for crypto ctx */
+  u_int32_t is_crypto_tkip;             /* tkip crypto done in s/w */
+  u_int32_t is_crypto_tkipenmic;        /* tkip en-MIC done in s/w */
+  u_int32_t is_crypto_tkipdemic;        /* tkip de-MIC done in s/w */
+  u_int32_t is_crypto_tkipcm;           /* tkip counter measures */
+  u_int32_t is_crypto_ccmp;             /* ccmp crypto done in s/w */
+  u_int32_t is_crypto_wep;              /* wep crypto done in s/w */
+  u_int32_t is_crypto_setkey_cipher;    /* cipher rejected key */
+  u_int32_t is_crypto_setkey_nokey;     /* no key index for setkey */
+  u_int32_t is_crypto_delkey;           /* driver key delete failed */
+  u_int32_t is_crypto_badcipher;        /* unknown cipher */
+  u_int32_t is_crypto_nocipher;         /* cipher not available */
+  u_int32_t is_crypto_attachfail;       /* cipher attach failed */
+  u_int32_t is_crypto_swfallback;       /* cipher fallback to s/w */
+  u_int32_t is_crypto_keyfail;          /* driver key alloc failed */
+  u_int32_t is_crypto_enmicfail;        /* en-MIC failed */
+  u_int32_t is_ibss_capmismatch;        /* merge failed-cap mismatch */
+  u_int32_t is_ibss_norate;             /* merge failed-rate mismatch */
+  u_int32_t is_ps_unassoc;              /* ps-poll for unassoc. sta */
+  u_int32_t is_ps_badaid;               /* ps-poll w/ incorrect aid */
+  u_int32_t is_ps_qempty;               /* ps-poll w/ nothing to send */
 };
 
 /*
  * Retrieve per-node statistics.
  */
 struct ieee80211req_sta_stats {
-       union {
-               /* NB: explicitly force 64-bit alignment */
-               u_int8_t macaddr[IEEE80211_ADDR_LEN];
-               u_int64_t pad;
-       } is_u;
-       struct ieee80211_nodestats is_stats;
+  union {
+    /* NB: explicitly force 64-bit alignment */
+    u_int8_t macaddr[IEEE80211_ADDR_LEN];
+    u_int64_t pad;
+  } is_u;
+  struct ieee80211_nodestats is_stats;
 };
 
 /*
@@ -203,105 +202,103 @@ struct ieee80211req_sta_stats {
  * to retrieve other data like stats, unicast key, etc.
  */
 struct ieee80211req_sta_info {
-       u_int16_t isi_len;              /* length (mult of 4) */
-       u_int16_t isi_freq;             /* MHz */
-       u_int16_t isi_flags;            /* channel flags */
-       u_int16_t isi_state;            /* state flags */
-       u_int8_t isi_authmode;          /* authentication algorithm */
-       u_int8_t isi_rssi;
-       u_int16_t isi_capinfo;          /* capabilities */
-       u_int8_t isi_athflags;          /* Atheros capabilities */
-       u_int8_t isi_erp;               /* ERP element */
-       u_int8_t isi_macaddr[IEEE80211_ADDR_LEN];
-       u_int8_t isi_nrates;            /* negotiated rates */
-       u_int8_t isi_rates[IEEE80211_RATE_MAXSIZE];
-       u_int8_t isi_txrate;            /* index to isi_rates[] */
-       u_int16_t isi_ie_len;           /* IE length */
-       u_int16_t isi_associd;          /* assoc response */
-       u_int16_t isi_txpower;          /* current tx power */
-       u_int16_t isi_vlan;             /* vlan tag */
-       u_int16_t isi_txseqs[17];       /* seq to be transmitted */
-       u_int16_t isi_rxseqs[17];       /* seq previous for qos frames*/
-       u_int16_t isi_inact;            /* inactivity timer */
-       u_int8_t isi_uapsd;             /* UAPSD queues */
-       u_int8_t isi_opmode;            /* sta operating mode */
+  u_int16_t isi_len;     /* length (mult of 4) */
+  u_int16_t isi_freq;    /* MHz */
+  u_int16_t isi_flags;   /* channel flags */
+  u_int16_t isi_state;   /* state flags */
+  u_int8_t isi_authmode; /* authentication algorithm */
+  u_int8_t isi_rssi;
+  u_int16_t isi_capinfo; /* capabilities */
+  u_int8_t isi_athflags; /* Atheros capabilities */
+  u_int8_t isi_erp;      /* ERP element */
+  u_int8_t isi_macaddr[IEEE80211_ADDR_LEN];
+  u_int8_t isi_nrates; /* negotiated rates */
+  u_int8_t isi_rates[IEEE80211_RATE_MAXSIZE];
+  u_int8_t isi_txrate;      /* index to isi_rates[] */
+  u_int16_t isi_ie_len;     /* IE length */
+  u_int16_t isi_associd;    /* assoc response */
+  u_int16_t isi_txpower;    /* current tx power */
+  u_int16_t isi_vlan;       /* vlan tag */
+  u_int16_t isi_txseqs[17]; /* seq to be transmitted */
+  u_int16_t isi_rxseqs[17]; /* seq previous for qos frames*/
+  u_int16_t isi_inact;      /* inactivity timer */
+  u_int8_t isi_uapsd;       /* UAPSD queues */
+  u_int8_t isi_opmode;      /* sta operating mode */
 
-       /* XXX frag state? */
-       /* variable length IE data */
+  /* XXX frag state? */
+  /* variable length IE data */
 };
 
-
 struct ath_stats {
-       u_int32_t ast_watchdog;         /* device reset by watchdog */
-       u_int32_t ast_hardware;         /* fatal hardware error interrupts */
-       u_int32_t ast_bmiss;            /* beacon miss interrupts */
-       u_int32_t ast_rxorn;            /* rx overrun interrupts */
-       u_int32_t ast_rxeol;            /* rx eol interrupts */
-       u_int32_t ast_txurn;            /* tx underrun interrupts */
-       u_int32_t ast_mib;              /* mib interrupts */
-       u_int32_t ast_tx_packets;       /* packet sent on the interface */
-       u_int32_t ast_tx_mgmt;          /* management frames transmitted */
-       u_int32_t ast_tx_discard;       /* frames discarded prior to assoc */
-       u_int32_t ast_tx_invalid;       /* frames discarded due to is device gone */
-       u_int32_t ast_tx_qstop;         /* tx queue stopped because it's full */
-       u_int32_t ast_tx_encap;         /* tx encapsulation failed */
-       u_int32_t ast_tx_nonode;        /* tx failed due to of no node */
-       u_int32_t ast_tx_nobuf;         /* tx failed due to of no tx buffer (data) */
-       u_int32_t ast_tx_nobufmgt;      /* tx failed due to of no tx buffer (mgmt)*/
-       u_int32_t ast_tx_xretries;      /* tx failed due to of too many retries */
-       u_int32_t ast_tx_fifoerr;       /* tx failed due to of FIFO underrun */
-       u_int32_t ast_tx_filtered;      /* tx failed due to xmit filtered */
-       u_int32_t ast_tx_shortretry;    /* tx on-chip retries (short) */
-       u_int32_t ast_tx_longretry;     /* tx on-chip retries (long) */
-       u_int32_t ast_tx_badrate;       /* tx failed due to of bogus xmit rate */
-       u_int32_t ast_tx_noack;         /* tx frames with no ack marked */
-       u_int32_t ast_tx_rts;           /* tx frames with rts enabled */
-       u_int32_t ast_tx_cts;           /* tx frames with cts enabled */
-       u_int32_t ast_tx_shortpre;      /* tx frames with short preamble */
-       u_int32_t ast_tx_altrate;       /* tx frames with alternate rate */
-       u_int32_t ast_tx_protect;       /* tx frames with protection */
-       u_int32_t ast_rx_orn;           /* rx failed due to of desc overrun */
-       u_int32_t ast_rx_crcerr;        /* rx failed due to of bad CRC */
-       u_int32_t ast_rx_fifoerr;       /* rx failed due to of FIFO overrun */
-       u_int32_t ast_rx_badcrypt;      /* rx failed due to of decryption */
-       u_int32_t ast_rx_badmic;        /* rx failed due to of MIC failure */
-       u_int32_t ast_rx_phyerr;        /* rx PHY error summary count */
-       u_int32_t ast_rx_phy[32];       /* rx PHY error per-code counts */
-       u_int32_t ast_rx_tooshort;      /* rx discarded due to frame too short */
-       u_int32_t ast_rx_toobig;        /* rx discarded due to frame too large */
-       u_int32_t ast_rx_nobuf;         /* rx setup failed due to of no skbuff */
-       u_int32_t ast_rx_packets;       /* packet recv on the interface */
-       u_int32_t ast_rx_mgt;           /* management frames received */
-       u_int32_t ast_rx_ctl;           /* control frames received */
-       int8_t ast_tx_rssi;             /* tx rssi of last ack */
-       int8_t ast_rx_rssi;             /* rx rssi from histogram */
-       u_int32_t ast_be_xmit;          /* beacons transmitted */
-       u_int32_t ast_be_nobuf;         /* no skbuff available for beacon */
-       u_int32_t ast_per_cal;          /* periodic calibration calls */
-       u_int32_t ast_per_calfail;      /* periodic calibration failed */
-       u_int32_t ast_per_rfgain;       /* periodic calibration rfgain reset */
-       u_int32_t ast_rate_calls;       /* rate control checks */
-       u_int32_t ast_rate_raise;       /* rate control raised xmit rate */
-       u_int32_t ast_rate_drop;        /* rate control dropped xmit rate */
-       u_int32_t ast_ant_defswitch;    /* rx/default antenna switches */
-       u_int32_t ast_ant_txswitch;     /* tx antenna switches */
-       u_int32_t ast_ant_rx[8];        /* rx frames with antenna */
-       u_int32_t ast_ant_tx[8];        /* tx frames with antenna */
+  u_int32_t ast_watchdog;      /* device reset by watchdog */
+  u_int32_t ast_hardware;      /* fatal hardware error interrupts */
+  u_int32_t ast_bmiss;         /* beacon miss interrupts */
+  u_int32_t ast_rxorn;         /* rx overrun interrupts */
+  u_int32_t ast_rxeol;         /* rx eol interrupts */
+  u_int32_t ast_txurn;         /* tx underrun interrupts */
+  u_int32_t ast_mib;           /* mib interrupts */
+  u_int32_t ast_tx_packets;    /* packet sent on the interface */
+  u_int32_t ast_tx_mgmt;       /* management frames transmitted */
+  u_int32_t ast_tx_discard;    /* frames discarded prior to assoc */
+  u_int32_t ast_tx_invalid;    /* frames discarded due to is device gone */
+  u_int32_t ast_tx_qstop;      /* tx queue stopped because it's full */
+  u_int32_t ast_tx_encap;      /* tx encapsulation failed */
+  u_int32_t ast_tx_nonode;     /* tx failed due to of no node */
+  u_int32_t ast_tx_nobuf;      /* tx failed due to of no tx buffer (data) */
+  u_int32_t ast_tx_nobufmgt;   /* tx failed due to of no tx buffer (mgmt)*/
+  u_int32_t ast_tx_xretries;   /* tx failed due to of too many retries */
+  u_int32_t ast_tx_fifoerr;    /* tx failed due to of FIFO underrun */
+  u_int32_t ast_tx_filtered;   /* tx failed due to xmit filtered */
+  u_int32_t ast_tx_shortretry; /* tx on-chip retries (short) */
+  u_int32_t ast_tx_longretry;  /* tx on-chip retries (long) */
+  u_int32_t ast_tx_badrate;    /* tx failed due to of bogus xmit rate */
+  u_int32_t ast_tx_noack;      /* tx frames with no ack marked */
+  u_int32_t ast_tx_rts;        /* tx frames with rts enabled */
+  u_int32_t ast_tx_cts;        /* tx frames with cts enabled */
+  u_int32_t ast_tx_shortpre;   /* tx frames with short preamble */
+  u_int32_t ast_tx_altrate;    /* tx frames with alternate rate */
+  u_int32_t ast_tx_protect;    /* tx frames with protection */
+  u_int32_t ast_rx_orn;        /* rx failed due to of desc overrun */
+  u_int32_t ast_rx_crcerr;     /* rx failed due to of bad CRC */
+  u_int32_t ast_rx_fifoerr;    /* rx failed due to of FIFO overrun */
+  u_int32_t ast_rx_badcrypt;   /* rx failed due to of decryption */
+  u_int32_t ast_rx_badmic;     /* rx failed due to of MIC failure */
+  u_int32_t ast_rx_phyerr;     /* rx PHY error summary count */
+  u_int32_t ast_rx_phy[32];    /* rx PHY error per-code counts */
+  u_int32_t ast_rx_tooshort;   /* rx discarded due to frame too short */
+  u_int32_t ast_rx_toobig;     /* rx discarded due to frame too large */
+  u_int32_t ast_rx_nobuf;      /* rx setup failed due to of no skbuff */
+  u_int32_t ast_rx_packets;    /* packet recv on the interface */
+  u_int32_t ast_rx_mgt;        /* management frames received */
+  u_int32_t ast_rx_ctl;        /* control frames received */
+  int8_t ast_tx_rssi;          /* tx rssi of last ack */
+  int8_t ast_rx_rssi;          /* rx rssi from histogram */
+  u_int32_t ast_be_xmit;       /* beacons transmitted */
+  u_int32_t ast_be_nobuf;      /* no skbuff available for beacon */
+  u_int32_t ast_per_cal;       /* periodic calibration calls */
+  u_int32_t ast_per_calfail;   /* periodic calibration failed */
+  u_int32_t ast_per_rfgain;    /* periodic calibration rfgain reset */
+  u_int32_t ast_rate_calls;    /* rate control checks */
+  u_int32_t ast_rate_raise;    /* rate control raised xmit rate */
+  u_int32_t ast_rate_drop;     /* rate control dropped xmit rate */
+  u_int32_t ast_ant_defswitch; /* rx/default antenna switches */
+  u_int32_t ast_ant_txswitch;  /* tx antenna switches */
+  u_int32_t ast_ant_rx[8];     /* rx frames with antenna */
+  u_int32_t ast_ant_tx[8];     /* tx frames with antenna */
 };
 
-#define        SIOCGATHSTATS                   (SIOCDEVPRIVATE+0)
-#define        SIOCGATHDIAG                    (SIOCDEVPRIVATE+1)
-#define        SIOCGATHRADARSIG                (SIOCDEVPRIVATE+2)
-#define        SIOCGATHHALDIAG                 (SIOCDEVPRIVATE+3)
-#define        SIOCG80211STATS                 (SIOCDEVPRIVATE+2)
+#define SIOCGATHSTATS (SIOCDEVPRIVATE + 0)
+#define SIOCGATHDIAG (SIOCDEVPRIVATE + 1)
+#define SIOCGATHRADARSIG (SIOCDEVPRIVATE + 2)
+#define SIOCGATHHALDIAG (SIOCDEVPRIVATE + 3)
+#define SIOCG80211STATS (SIOCDEVPRIVATE + 2)
 /* NB: require in+out parameters so cannot use wireless extensions, yech */
-#define        IEEE80211_IOCTL_GETKEY          (SIOCDEVPRIVATE+3)
-#define        IEEE80211_IOCTL_GETWPAIE        (SIOCDEVPRIVATE+4)
-#define        IEEE80211_IOCTL_STA_STATS       (SIOCDEVPRIVATE+5)
-#define        IEEE80211_IOCTL_STA_INFO        (SIOCDEVPRIVATE+6)
-#define        SIOC80211IFCREATE               (SIOCDEVPRIVATE+7)
-#define        SIOC80211IFDESTROY              (SIOCDEVPRIVATE+8)
-#define        IEEE80211_IOCTL_SCAN_RESULTS    (SIOCDEVPRIVATE+9)
-
+#define IEEE80211_IOCTL_GETKEY (SIOCDEVPRIVATE + 3)
+#define IEEE80211_IOCTL_GETWPAIE (SIOCDEVPRIVATE + 4)
+#define IEEE80211_IOCTL_STA_STATS (SIOCDEVPRIVATE + 5)
+#define IEEE80211_IOCTL_STA_INFO (SIOCDEVPRIVATE + 6)
+#define SIOC80211IFCREATE (SIOCDEVPRIVATE + 7)
+#define SIOC80211IFDESTROY (SIOCDEVPRIVATE + 8)
+#define IEEE80211_IOCTL_SCAN_RESULTS (SIOCDEVPRIVATE + 9)
 
 #endif
index fd87b38..799e09d 100644 (file)
@@ -73,9 +73,9 @@ static int mec_match(__attribute__((unused)) const data_set_t *ds, /* {{{ */
 } /* }}} int mec_match */
 
 void module_register(void) {
-  fc_register_match(
-      "empty_counter",
-      (match_proc_t){
-          .create = mec_create, .destroy = mec_destroy, .match = mec_match,
-      });
+  fc_register_match("empty_counter", (match_proc_t){
+                                         .create = mec_create,
+                                         .destroy = mec_destroy,
+                                         .match = mec_match,
+                                     });
 } /* module_register */
index 4052ad5..99f0709 100644 (file)
@@ -336,21 +336,22 @@ static int mr_match(const data_set_t __attribute__((unused)) * ds, /* {{{ */
   if (mr_match_regexen(m->type_instance, vl->type_instance) ==
       FC_MATCH_NO_MATCH)
     return nomatch_value;
-  if (vl->meta != NULL) {
-    for (llentry_t *e = llist_head(m->meta); e != NULL; e = e->next) {
-      mr_regex_t *meta_re = (mr_regex_t *)e->value;
-      char *value;
-      int status = meta_data_get_string(vl->meta, e->key, &value);
-      if (status == (-ENOENT)) /* key is not present */
-        return nomatch_value;
-      if (status != 0) /* some other problem */
-        continue;      /* error will have already been printed. */
-      if (mr_match_regexen(meta_re, value) == FC_MATCH_NO_MATCH) {
-        sfree(value);
-        return nomatch_value;
-      }
+  for (llentry_t *e = llist_head(m->meta); e != NULL; e = e->next) {
+    mr_regex_t *meta_re = (mr_regex_t *)e->value;
+    char *value;
+    int status;
+    if (vl->meta == NULL)
+      return nomatch_value;
+    status = meta_data_get_string(vl->meta, e->key, &value);
+    if (status == (-ENOENT)) /* key is not present */
+      return nomatch_value;
+    if (status != 0) /* some other problem */
+      continue;      /* error will have already been printed. */
+    if (mr_match_regexen(meta_re, value) == FC_MATCH_NO_MATCH) {
       sfree(value);
+      return nomatch_value;
     }
+    sfree(value);
   }
 
   return match_value;
index 0cce0c6..d71195f 100644 (file)
@@ -90,14 +90,16 @@ static int socket_reinit(socket_adapter_t *self);
 static int socket_receive(socket_adapter_t *self, FILE **p_file);
 
 static mcelog_config_t g_mcelog_config = {
-    .logfile = "/var/log/mcelog", .persist = false,
+    .logfile = "/var/log/mcelog",
+    .persist = false,
 };
 
 static socket_adapter_t socket_adapter = {
     .sock_fd = -1,
     .unix_sock =
         {
-            .sun_family = AF_UNIX, .sun_path = "/var/run/mcelog-client",
+            .sun_family = AF_UNIX,
+            .sun_path = "/var/run/mcelog-client",
         },
     .lock = PTHREAD_RWLOCK_INITIALIZER,
     .close = socket_close,
@@ -523,7 +525,8 @@ static int socket_receive(socket_adapter_t *self, FILE **pp_file) {
   int res = -1;
   pthread_rwlock_rdlock(&self->lock);
   struct pollfd poll_fd = {
-      .fd = self->sock_fd, .events = POLLIN | POLLPRI,
+      .fd = self->sock_fd,
+      .events = POLLIN | POLLPRI,
   };
 
   if ((res = poll(&poll_fd, 1, MCELOG_POLL_TIMEOUT)) <= 0) {
index 0baf6c2..c00f53e 100644 (file)
@@ -171,7 +171,8 @@ static int memcached_connect_inet(memcached_t *st) {
 
     /* Wait until connection establishes */
     struct pollfd pollfd = {
-        .fd = fd, .events = POLLOUT,
+        .fd = fd,
+        .events = POLLOUT,
     };
     do
       status = poll(&pollfd, 1, MEMCACHED_CONNECT_TIMEOUT);
@@ -226,7 +227,8 @@ static int memcached_query_daemon(char *buffer, size_t buffer_size,
   }
 
   struct pollfd pollfd = {
-      .fd = st->fd, .events = POLLOUT,
+      .fd = st->fd,
+      .events = POLLOUT,
   };
 
   do
@@ -346,7 +348,8 @@ static void submit_derive2(const char *type, const char *type_inst,
                            derive_t value0, derive_t value1, memcached_t *st) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = value0}, {.derive = value1},
+      {.derive = value0},
+      {.derive = value1},
   };
 
   memcached_init_vl(&vl, st);
@@ -377,7 +380,8 @@ static void submit_gauge2(const char *type, const char *type_inst,
                           gauge_t value0, gauge_t value1, memcached_t *st) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.gauge = value0}, {.gauge = value1},
+      {.gauge = value0},
+      {.gauge = value1},
   };
 
   memcached_init_vl(&vl, st);
@@ -509,6 +513,13 @@ static int memcached_read(user_data_t *user_data) {
     }
 
     /*
+     * Number of secs since the server started
+     */
+    else if (FIELD_IS("uptime")) {
+      submit_gauge("uptime", NULL, atof(fields[2]), st);
+    }
+
+    /*
      * Number of bytes used and available (total - used)
      */
     else if (FIELD_IS("bytes")) {
@@ -685,7 +696,8 @@ static int memcached_add_read_callback(memcached_t *st) {
       /* callback  = */ memcached_read,
       /* interval  = */ 0,
       &(user_data_t){
-          .data = st, .free_func = memcached_free,
+          .data = st,
+          .free_func = memcached_free,
       });
 } /* int memcached_add_read_callback */
 
index 4a3a772..107e867 100644 (file)
@@ -28,7 +28,9 @@
 #include "plugin.h"
 #include "utils/common/common.h"
 
-#ifdef HAVE_SYS_SYSCTL_H
+#if (defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME)) ||              \
+    defined(__OpenBSD__)
+/* Implies BSD variant */
 #include <sys/sysctl.h>
 #endif
 #ifdef HAVE_SYS_VMMETER_H
@@ -80,9 +82,10 @@ static kstat_t *ksp;
 static kstat_t *ksz;
 /* #endif HAVE_LIBKSTAT */
 
-#elif HAVE_SYSCTL
+#elif HAVE_SYSCTL && __OpenBSD__
+/* OpenBSD variant does not have sysctlbyname */
 static int pagesize;
-/* #endif HAVE_SYSCTL */
+/* #endif HAVE_SYSCTL && __OpenBSD__ */
 
 #elif HAVE_LIBSTATGRAB
 /* no global variables */
@@ -118,7 +121,7 @@ static int memory_init(void) {
 #if HAVE_HOST_STATISTICS
   port_host = mach_host_self();
   host_page_size(port_host, &pagesize);
-/* #endif HAVE_HOST_STATISTICS */
+  /* #endif HAVE_HOST_STATISTICS */
 
 #elif HAVE_SYSCTLBYNAME
 /* no init stuff */
@@ -140,15 +143,16 @@ static int memory_init(void) {
     return -1;
   }
 
-/* #endif HAVE_LIBKSTAT */
+    /* #endif HAVE_LIBKSTAT */
 
-#elif HAVE_SYSCTL
+#elif HAVE_SYSCTL && __OpenBSD__
+  /* OpenBSD variant does not have sysctlbyname */
   pagesize = getpagesize();
   if (pagesize <= 0) {
     ERROR("memory plugin: Invalid pagesize: %i", pagesize);
     return -1;
   }
-/* #endif HAVE_SYSCTL */
+    /* #endif HAVE_SYSCTL && __OpenBSD__ */
 
 #elif HAVE_LIBSTATGRAB
 /* no init stuff */
@@ -218,7 +222,7 @@ static int memory_read_internal(value_list_t *vl) {
 
   MEMORY_SUBMIT("wired", wired, "active", active, "inactive", inactive, "free",
                 free);
-/* #endif HAVE_HOST_STATISTICS */
+  /* #endif HAVE_HOST_STATISTICS */
 
 #elif HAVE_SYSCTLBYNAME
   /*
@@ -259,7 +263,7 @@ static int memory_read_internal(value_list_t *vl) {
                 (gauge_t)sysctl_vals[3], "active", (gauge_t)sysctl_vals[4],
                 "inactive", (gauge_t)sysctl_vals[5], "cache",
                 (gauge_t)sysctl_vals[6]);
-/* #endif HAVE_SYSCTLBYNAME */
+  /* #endif HAVE_SYSCTLBYNAME */
 
 #elif KERNEL_LINUX
   FILE *fh;
@@ -334,7 +338,7 @@ static int memory_read_internal(value_list_t *vl) {
   else
     MEMORY_SUBMIT("used", mem_used, "buffered", mem_buffered, "cached",
                   mem_cached, "free", mem_free, "slab", mem_slab_total);
-/* #endif KERNEL_LINUX */
+    /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKSTAT
   /* Most of the additions here were taken as-is from the k9toolkit from
@@ -406,9 +410,10 @@ static int memory_read_internal(value_list_t *vl) {
   MEMORY_SUBMIT("used", (gauge_t)mem_used, "free", (gauge_t)mem_free, "locked",
                 (gauge_t)mem_lock, "kernel", (gauge_t)mem_kern, "arc",
                 (gauge_t)arcsize, "unusable", (gauge_t)mem_unus);
-/* #endif HAVE_LIBKSTAT */
+  /* #endif HAVE_LIBKSTAT */
 
-#elif HAVE_SYSCTL
+#elif HAVE_SYSCTL && __OpenBSD__
+  /* OpenBSD variant does not have HAVE_SYSCTLBYNAME */
   int mib[] = {CTL_VM, VM_METER};
   struct vmtotal vmtotal = {0};
   gauge_t mem_active;
@@ -430,7 +435,7 @@ static int memory_read_internal(value_list_t *vl) {
 
   MEMORY_SUBMIT("active", mem_active, "inactive", mem_inactive, "free",
                 mem_free);
-/* #endif HAVE_SYSCTL */
+  /* #endif HAVE_SYSCTL && __OpenBSD__ */
 
 #elif HAVE_LIBSTATGRAB
   sg_mem_stats *ios;
@@ -441,7 +446,7 @@ static int memory_read_internal(value_list_t *vl) {
 
   MEMORY_SUBMIT("used", (gauge_t)ios->used, "cached", (gauge_t)ios->cache,
                 "free", (gauge_t)ios->free);
-/* #endif HAVE_LIBSTATGRAB */
+  /* #endif HAVE_LIBSTATGRAB */
 
 #elif HAVE_PERFSTAT
   perfstat_memory_total_t pmemory = {0};
index 6924eaf..584d2e2 100644 (file)
--- a/src/mic.c
+++ b/src/mic.c
@@ -132,7 +132,7 @@ static void mic_submit_memory_use(int micnumber, const char *type_instance,
   vl.values_len = 1;
 
   strncpy(vl.plugin, "mic", sizeof(vl.plugin));
-  snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
+  ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
   strncpy(vl.type, "memory", sizeof(vl.type));
   strncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
 
@@ -164,7 +164,7 @@ static void mic_submit_temp(int micnumber, const char *type, gauge_t value) {
   vl.values_len = 1;
 
   strncpy(vl.plugin, "mic", sizeof(vl.plugin));
-  snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
+  ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
   strncpy(vl.type, "temperature", sizeof(vl.type));
   strncpy(vl.type_instance, type, sizeof(vl.type_instance));
 
@@ -206,10 +206,10 @@ static void mic_submit_cpu(int micnumber, const char *type_instance, int core,
 
   strncpy(vl.plugin, "mic", sizeof(vl.plugin));
   if (core < 0) /* global aggregation */
-    snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
+    ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
   else /* per-core statistics */
-    snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i-cpu-%i",
-             micnumber, core);
+    ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i-cpu-%i",
+              micnumber, core);
   strncpy(vl.type, "cpu", sizeof(vl.type));
   strncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
 
@@ -258,7 +258,7 @@ static void mic_submit_power(int micnumber, const char *type,
   vl.values_len = 1;
 
   strncpy(vl.plugin, "mic", sizeof(vl.plugin));
-  snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
+  ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
   strncpy(vl.type, type, sizeof(vl.type));
   strncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
 
index 04232c3..e36f3da 100644 (file)
@@ -259,7 +259,7 @@ static int mb_submit(mb_host_t *host, mb_slave_t *slave, /* {{{ */
     return EINVAL;
 
   if (slave->instance[0] == 0)
-    snprintf(slave->instance, sizeof(slave->instance), "slave_%i", slave->id);
+    ssnprintf(slave->instance, sizeof(slave->instance), "slave_%i", slave->id);
 
   vl.values = &value;
   vl.values_len = 1;
@@ -341,7 +341,7 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */
   host->is_connected = true;
   return 0;
 } /* }}} int mb_init_connection */
-/* #endif LEGACY_LIBMODBUS */
+  /* #endif LEGACY_LIBMODBUS */
 
 #else /* if !LEGACY_LIBMODBUS */
 /* Version 2.9.2 */
@@ -1072,13 +1072,14 @@ static int mb_config_add_host(oconfig_item_t *ci) /* {{{ */
   if (status == 0) {
     char name[1024];
 
-    snprintf(name, sizeof(name), "modbus-%s", host->host);
+    ssnprintf(name, sizeof(name), "modbus-%s", host->host);
 
     plugin_register_complex_read(/* group = */ NULL, name,
                                  /* callback = */ mb_read,
                                  /* interval = */ interval,
                                  &(user_data_t){
-                                     .data = host, .free_func = host_free,
+                                     .data = host,
+                                     .free_func = host_free,
                                  });
   } else {
     host_free(host);
index 630114e..a44f4c8 100644 (file)
@@ -462,7 +462,7 @@ static int format_topic(char *buf, size_t buf_len, data_set_t const *ds,
   if (status != 0)
     return status;
 
-  status = snprintf(buf, buf_len, "%s/%s", conf->topic_prefix, name);
+  status = ssnprintf(buf, buf_len, "%s/%s", conf->topic_prefix, name);
   if ((status < 0) || (((size_t)status) >= buf_len))
     return ENOMEM;
 
@@ -599,7 +599,7 @@ static int mqtt_config_publisher(oconfig_item_t *ci) {
       ERROR("mqtt plugin: Unknown config option: %s", child->key);
   }
 
-  snprintf(cb_name, sizeof(cb_name), "mqtt/%s", conf->name);
+  ssnprintf(cb_name, sizeof(cb_name), "mqtt/%s", conf->name);
   plugin_register_write(cb_name, mqtt_write,
                         &(user_data_t){
                             .data = conf,
index 0eba01f..aafd4db 100644 (file)
@@ -218,14 +218,15 @@ static int mysql_config_database(oconfig_item_t *ci) /* {{{ */
           (db->database != NULL) ? db->database : "<default>");
 
     if (db->instance != NULL)
-      snprintf(cb_name, sizeof(cb_name), "mysql-%s", db->instance);
+      ssnprintf(cb_name, sizeof(cb_name), "mysql-%s", db->instance);
     else
       sstrncpy(cb_name, "mysql", sizeof(cb_name));
 
     plugin_register_complex_read(
         /* group = */ NULL, cb_name, mysql_read, /* interval = */ 0,
         &(user_data_t){
-            .data = db, .free_func = mysql_database_free,
+            .data = db,
+            .free_func = mysql_database_free,
         });
   } else {
     mysql_database_free(db);
@@ -354,7 +355,8 @@ static void derive_submit(const char *type, const char *type_instance,
 
 static void traffic_submit(derive_t rx, derive_t tx, mysql_database_t *db) {
   value_t values[] = {
-      {.derive = rx}, {.derive = tx},
+      {.derive = rx},
+      {.derive = tx},
   };
 
   submit("mysql_octets", NULL, values, STATIC_ARRAY_SIZE(values), db);
@@ -500,15 +502,15 @@ static int mysql_read_slave_stats(mysql_database_t *db, MYSQL *con) {
     if (((io == NULL) || (strcasecmp(io, "yes") != 0)) &&
         (db->slave_io_running)) {
       n.severity = NOTIF_WARNING;
-      snprintf(n.message, sizeof(n.message),
-               "slave I/O thread not started or not connected to master");
+      ssnprintf(n.message, sizeof(n.message),
+                "slave I/O thread not started or not connected to master");
       plugin_dispatch_notification(&n);
       db->slave_io_running = false;
     } else if (((io != NULL) && (strcasecmp(io, "yes") == 0)) &&
                (!db->slave_io_running)) {
       n.severity = NOTIF_OKAY;
-      snprintf(n.message, sizeof(n.message),
-               "slave I/O thread started and connected to master");
+      ssnprintf(n.message, sizeof(n.message),
+                "slave I/O thread started and connected to master");
       plugin_dispatch_notification(&n);
       db->slave_io_running = true;
     }
@@ -516,13 +518,13 @@ static int mysql_read_slave_stats(mysql_database_t *db, MYSQL *con) {
     if (((sql == NULL) || (strcasecmp(sql, "yes") != 0)) &&
         (db->slave_sql_running)) {
       n.severity = NOTIF_WARNING;
-      snprintf(n.message, sizeof(n.message), "slave SQL thread not started");
+      ssnprintf(n.message, sizeof(n.message), "slave SQL thread not started");
       plugin_dispatch_notification(&n);
       db->slave_sql_running = false;
     } else if (((sql != NULL) && (strcasecmp(sql, "yes") == 0)) &&
                (!db->slave_sql_running)) {
       n.severity = NOTIF_OKAY;
-      snprintf(n.message, sizeof(n.message), "slave SQL thread started");
+      ssnprintf(n.message, sizeof(n.message), "slave SQL thread started");
       plugin_dispatch_notification(&n);
       db->slave_sql_running = true;
     }
index 1b510d2..43aaa7a 100644 (file)
@@ -643,7 +643,8 @@ static int submit_two_derive(const char *host,
                              derive_t val0, derive_t val1, cdtime_t timestamp,
                              cdtime_t interval) {
   value_t values[] = {
-      {.derive = val0}, {.derive = val1},
+      {.derive = val0},
+      {.derive = val1},
   };
 
   return submit_values(host, plugin_inst, type, type_inst, values,
@@ -666,7 +667,8 @@ static int submit_two_gauge(const char *host, const char *plugin_inst, /* {{{ */
                             gauge_t val0, gauge_t val1, cdtime_t timestamp,
                             cdtime_t interval) {
   value_t values[] = {
-      {.gauge = val0}, {.gauge = val1},
+      {.gauge = val0},
+      {.gauge = val1},
   };
 
   return submit_values(host, plugin_inst, type, type_inst, values,
@@ -773,14 +775,13 @@ static int submit_volume_perf_data(const char *hostname, /* {{{ */
   if ((hostname == NULL) || (old_data == NULL) || (new_data == NULL))
     return -1;
 
-  snprintf(plugin_instance, sizeof(plugin_instance), "volume-%s",
-           old_data->name);
+  ssnprintf(plugin_instance, sizeof(plugin_instance), "volume-%s",
+            old_data->name);
 
   /* Check for and submit disk-octet values */
   if (HAS_ALL_FLAGS(old_data->flags, CFG_VOLUME_PERF_IO) &&
-      HAS_ALL_FLAGS(new_data->flags,
-                    HAVE_VOLUME_PERF_BYTES_READ |
-                        HAVE_VOLUME_PERF_BYTES_WRITE)) {
+      HAS_ALL_FLAGS(new_data->flags, HAVE_VOLUME_PERF_BYTES_READ |
+                                         HAVE_VOLUME_PERF_BYTES_WRITE)) {
     submit_two_derive(
         hostname, plugin_instance, "disk_octets", /* type instance = */ NULL,
         (derive_t)new_data->read_bytes, (derive_t)new_data->write_bytes,
@@ -798,15 +799,15 @@ static int submit_volume_perf_data(const char *hostname, /* {{{ */
   }
 
   /* Check for, calculate and submit disk-latency values */
-  if (HAS_ALL_FLAGS(old_data->flags,
-                    CFG_VOLUME_PERF_LATENCY | HAVE_VOLUME_PERF_OPS_READ |
-                        HAVE_VOLUME_PERF_OPS_WRITE |
-                        HAVE_VOLUME_PERF_LATENCY_READ |
-                        HAVE_VOLUME_PERF_LATENCY_WRITE) &&
-      HAS_ALL_FLAGS(new_data->flags,
-                    HAVE_VOLUME_PERF_OPS_READ | HAVE_VOLUME_PERF_OPS_WRITE |
-                        HAVE_VOLUME_PERF_LATENCY_READ |
-                        HAVE_VOLUME_PERF_LATENCY_WRITE)) {
+  if (HAS_ALL_FLAGS(old_data->flags, CFG_VOLUME_PERF_LATENCY |
+                                         HAVE_VOLUME_PERF_OPS_READ |
+                                         HAVE_VOLUME_PERF_OPS_WRITE |
+                                         HAVE_VOLUME_PERF_LATENCY_READ |
+                                         HAVE_VOLUME_PERF_LATENCY_WRITE) &&
+      HAS_ALL_FLAGS(new_data->flags, HAVE_VOLUME_PERF_OPS_READ |
+                                         HAVE_VOLUME_PERF_OPS_WRITE |
+                                         HAVE_VOLUME_PERF_LATENCY_READ |
+                                         HAVE_VOLUME_PERF_LATENCY_WRITE)) {
     gauge_t latency_per_op_read;
     gauge_t latency_per_op_write;
 
@@ -1404,11 +1405,10 @@ static int cna_submit_volume_usage_data(const char *hostname, /* {{{ */
     uint64_t snap_reserve_free = v->snap_reserved;
     uint64_t snap_norm_used = v->snap_used;
 
-    snprintf(plugin_instance, sizeof(plugin_instance), "volume-%s", v->name);
+    ssnprintf(plugin_instance, sizeof(plugin_instance), "volume-%s", v->name);
 
-    if (HAS_ALL_FLAGS(v->flags,
-                      HAVE_VOLUME_USAGE_SNAP_USED |
-                          HAVE_VOLUME_USAGE_SNAP_RSVD)) {
+    if (HAS_ALL_FLAGS(v->flags, HAVE_VOLUME_USAGE_SNAP_USED |
+                                    HAVE_VOLUME_USAGE_SNAP_RSVD)) {
       if (v->snap_reserved > v->snap_used) {
         snap_reserve_free = v->snap_reserved - v->snap_used;
         snap_reserve_used = v->snap_used;
@@ -1422,9 +1422,8 @@ static int cna_submit_volume_usage_data(const char *hostname, /* {{{ */
 
     /* The space used by snapshots but not reserved for them is included in
      * both, norm_used and snap_norm_used. If possible, subtract this here. */
-    if (HAS_ALL_FLAGS(v->flags,
-                      HAVE_VOLUME_USAGE_NORM_USED |
-                          HAVE_VOLUME_USAGE_SNAP_USED)) {
+    if (HAS_ALL_FLAGS(v->flags, HAVE_VOLUME_USAGE_NORM_USED |
+                                    HAVE_VOLUME_USAGE_SNAP_USED)) {
       if (norm_used >= snap_norm_used)
         norm_used -= snap_norm_used;
       else {
@@ -1466,9 +1465,8 @@ static int cna_submit_volume_usage_data(const char *hostname, /* {{{ */
                     "df_complex", "snap_reserved", (double)snap_reserve_free,
                     /* timestamp = */ 0, interval);
 
-    if (HAS_ALL_FLAGS(v->flags,
-                      HAVE_VOLUME_USAGE_SNAP_USED |
-                          HAVE_VOLUME_USAGE_SNAP_RSVD))
+    if (HAS_ALL_FLAGS(v->flags, HAVE_VOLUME_USAGE_SNAP_USED |
+                                    HAVE_VOLUME_USAGE_SNAP_RSVD))
       submit_double(hostname, /* plugin instance = */ plugin_instance,
                     "df_complex", "snap_reserve_used",
                     (double)snap_reserve_used, /* timestamp = */ 0, interval);
@@ -1498,12 +1496,13 @@ static int cna_change_volume_status(const char *hostname, /* {{{ */
 
   if ((v->flags & IS_VOLUME_USAGE_OFFLINE) != 0) {
     n.severity = NOTIF_OKAY;
-    snprintf(n.message, sizeof(n.message), "Volume %s is now online.", v->name);
+    ssnprintf(n.message, sizeof(n.message), "Volume %s is now online.",
+              v->name);
     v->flags &= ~IS_VOLUME_USAGE_OFFLINE;
   } else {
     n.severity = NOTIF_WARNING;
-    snprintf(n.message, sizeof(n.message), "Volume %s is now offline.",
-             v->name);
+    ssnprintf(n.message, sizeof(n.message), "Volume %s is now offline.",
+              v->name);
     v->flags |= IS_VOLUME_USAGE_OFFLINE;
   }
 
@@ -1832,8 +1831,8 @@ static int cna_handle_quota_data(const host_config_t *host, /* {{{ */
     if (volume_name == NULL)
       continue;
 
-    snprintf(plugin_instance, sizeof(plugin_instance), "quota-%s-%s",
-             volume_name, tree_name);
+    ssnprintf(plugin_instance, sizeof(plugin_instance), "quota-%s-%s",
+              volume_name, tree_name);
 
     value = na_child_get_uint64(elem_quota, "disk-used", UINT64_MAX);
     if (value != UINT64_MAX) {
@@ -1945,8 +1944,8 @@ static int cna_handle_snapvault_data(const char *hostname, /* {{{ */
       continue;
 
     /* possible TODO: make plugin instance configurable */
-    snprintf(plugin_instance, sizeof(plugin_instance), "snapvault-%s",
-             dest_path);
+    ssnprintf(plugin_instance, sizeof(plugin_instance), "snapvault-%s",
+              dest_path);
     submit_double(hostname, plugin_instance, /* type = */ "delay", NULL,
                   (double)value, /* timestamp = */ 0, interval);
 
@@ -2787,17 +2786,18 @@ static int cna_register_host(host_config_t *host) /* {{{ */
   char cb_name[256];
 
   if (host->vfiler)
-    snprintf(cb_name, sizeof(cb_name), "netapp-%s-%s", host->name,
-             host->vfiler);
+    ssnprintf(cb_name, sizeof(cb_name), "netapp-%s-%s", host->name,
+              host->vfiler);
   else
-    snprintf(cb_name, sizeof(cb_name), "netapp-%s", host->name);
+    ssnprintf(cb_name, sizeof(cb_name), "netapp-%s", host->name);
 
   plugin_register_complex_read(
       /* group = */ NULL, cb_name,
       /* callback  = */ cna_read,
       /* interval  = */ host->interval,
       &(user_data_t){
-          .data = host, .free_func = (void *)free_host_config,
+          .data = host,
+          .free_func = (void *)free_host_config,
       });
 
   return 0;
index 37c2e29..b998cf3 100644 (file)
@@ -198,7 +198,8 @@ static void submit_two(const char *dev, const char *type,
                        const char *type_instance, derive_t rx, derive_t tx) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = rx}, {.derive = tx},
+      {.derive = rx},
+      {.derive = tx},
   };
 
   vl.values = values;
@@ -509,8 +510,8 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) {
     if (strcmp(tc_type, "filter") == 0)
       numberic_id = tm->tcm_parent;
 
-    snprintf(tc_inst, sizeof(tc_inst), "%s-%x:%x", kind, numberic_id >> 16,
-             numberic_id & 0x0000FFFF);
+    ssnprintf(tc_inst, sizeof(tc_inst), "%s-%x:%x", kind, numberic_id >> 16,
+              numberic_id & 0x0000FFFF);
   }
 
   DEBUG("netlink plugin: qos_filter_cb: got %s for %s (%i).", tc_type, dev,
@@ -541,8 +542,8 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) {
 
       stats_submitted = true;
 
-      int r = snprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type,
-                       tc_inst);
+      int r = ssnprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type,
+                        tc_inst);
       if ((size_t)r >= sizeof(type_instance)) {
         ERROR("netlink plugin: type_instance truncated to %zu bytes, need %d",
               sizeof(type_instance), r);
@@ -580,8 +581,8 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) {
     if (!stats_submitted && ts != NULL) {
       char type_instance[DATA_MAX_NAME_LEN];
 
-      int r = snprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type,
-                       tc_inst);
+      int r = ssnprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type,
+                        tc_inst);
       if ((size_t)r >= sizeof(type_instance)) {
         ERROR("netlink plugin: type_instance truncated to %zu bytes, need %d",
               sizeof(type_instance), r);
@@ -637,7 +638,7 @@ static int ir_config(const char *key, const char *value) {
   } else if ((strcasecmp(key, "QDisc") == 0) ||
              (strcasecmp(key, "Class") == 0) ||
              (strcasecmp(key, "Filter") == 0)) {
-    if ((fields_num < 1) || (fields_num > 2)) {
+    if (fields_num > 2) {
       ERROR("netlink plugin: Invalid number of fields for option "
             "`%s'. Got %i, expected 1 or 2.",
             key, fields_num);
index f6f0ac1..613caa7 100644 (file)
@@ -142,6 +142,7 @@ typedef struct sockent {
   } data;
 
   struct sockent *next;
+  pthread_mutex_t lock;
 } sockent_t;
 
 /*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
@@ -381,7 +382,7 @@ static bool check_send_notify_okay(const notification_t *n) /* {{{ */
         LOG_ERR, &complain_forwarding,
         "network plugin: A notification has been received via the network "
         "and forwarding is enabled. Forwarding of notifications is currently "
-        "not supported, because there is not loop-deteciton available. "
+        "not supported, because there is not loop-detection available. "
         "Please contact the collectd mailing list if you need this "
         "feature.");
   }
@@ -1108,7 +1109,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */
 
   return 0;
 } /* }}} int parse_part_sign_sha256 */
-/* #endif HAVE_GCRYPT_H */
+  /* #endif HAVE_GCRYPT_H */
 
 #else  /* if !HAVE_GCRYPT_H */
 static int parse_part_sign_sha256(sockent_t *se, /* {{{ */
@@ -1263,7 +1264,7 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */
 
   return 0;
 } /* }}} int parse_part_encr_aes256 */
-/* #endif HAVE_GCRYPT_H */
+  /* #endif HAVE_GCRYPT_H */
 
 #else  /* if !HAVE_GCRYPT_H */
 static int parse_part_encr_aes256(sockent_t *se, /* {{{ */
@@ -1540,6 +1541,7 @@ static void sockent_destroy(sockent_t *se) /* {{{ */
 
     sfree(se->node);
     sfree(se->service);
+    pthread_mutex_destroy(&se->lock);
 
     if (se->type == SOCKENT_TYPE_CLIENT)
       free_sockent_client(&se->data.client);
@@ -1668,7 +1670,7 @@ static int network_set_interface(const sockent_t *se,
       ERROR("network plugin: setsockopt (bind-if): %s", STRERRNO);
       return -1;
     }
-/* #endif HAVE_IF_INDEXTONAME && SO_BINDTODEVICE */
+      /* #endif HAVE_IF_INDEXTONAME && SO_BINDTODEVICE */
 
 #else
     WARNING("network plugin: Cannot set the interface on a unicast "
@@ -1858,6 +1860,7 @@ static sockent_t *sockent_create(int type) /* {{{ */
   se->service = NULL;
   se->interface = 0;
   se->next = NULL;
+  pthread_mutex_init(&se->lock, NULL);
 
   if (type == SOCKENT_TYPE_SERVER) {
     se->data.server.fd = NULL;
@@ -1949,6 +1952,8 @@ static int sockent_client_disconnect(sockent_t *se) /* {{{ */
     client->fd = -1;
   }
 
+  DEBUG("network plugin: free (se = %p, addr = %p);", (void *)se,
+        (void *)client->addr);
   sfree(client->addr);
   client->addrlen = 0;
 
@@ -2020,6 +2025,8 @@ static int sockent_client_connect(sockent_t *se) /* {{{ */
       client->fd = -1;
       continue;
     }
+    DEBUG("network plugin: alloc (se = %p, addr = %p);", (void *)se,
+          (void *)client->addr);
 
     assert(sizeof(*client->addr) >= ai_ptr->ai_addrlen);
     memcpy(client->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
@@ -2541,6 +2548,7 @@ static void network_send_buffer(char *buffer, size_t buffer_len) /* {{{ */
         buffer_len);
 
   for (sockent_t *se = sending_sockets; se != NULL; se = se->next) {
+    pthread_mutex_lock(&se->lock);
 #if HAVE_GCRYPT_H
     if (se->data.client.security_level == SECURITY_LEVEL_ENCRYPT)
       network_send_buffer_encrypted(se, buffer, buffer_len);
@@ -2549,6 +2557,7 @@ static void network_send_buffer(char *buffer, size_t buffer_len) /* {{{ */
     else /* if (se->data.client.security_level == SECURITY_LEVEL_NONE) */
 #endif   /* HAVE_GCRYPT_H */
       network_send_buffer_plain(se, buffer, buffer_len);
+    pthread_mutex_unlock(&se->lock);
   } /* for (sending_sockets) */
 } /* }}} void network_send_buffer */
 
@@ -2753,6 +2762,7 @@ network_config_set_bind_address(const oconfig_item_t *ci,
   *bind_address = malloc(sizeof(**bind_address));
   if (*bind_address == NULL) {
     ERROR("network plugin: network_config_set_bind_address: malloc failed.");
+    freeaddrinfo(res);
     return -1;
   }
   (*bind_address)->ss_family = res->ai_family;
diff --git a/src/network_test.c b/src/network_test.c
new file mode 100644 (file)
index 0000000..ae4875c
--- /dev/null
@@ -0,0 +1,255 @@
+/**
+ * Copyright (C) 2019       Florian octo Forster
+ *
+ * ISC License (ISC)
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#define TEST_PLUGIN_NETWORK 1
+
+#include "network.c" /* (sic) */
+
+#include "testing.h"
+
+char *raw_packet_data[] = {
+    "0000000e6c6f63616c686f7374000008000c1513676ac3a6e0970009000c00000002800000"
+    "000002000973776170000004000973776170000005000966726565000006000f0001010000"
+    "0080ff610f420008000c1513676ac3a8fc120004000c737761705f696f0000050007696e00"
+    "0006000f00010200000000000000000008000c1513676ac3a9077d000500086f7574000006"
+    "000f00010200000000000000000008000c1513676ac3bd2a8c0002000e696e746572666163"
+    "65000003000965746830000004000e69665f6f637465747300000500050000060018000202"
+    "02000000000000000000000000000000000008000c1513676ac3bd5a970004000e69665f65"
+    "72726f7273000006001800020202000000000000000000000000000000000008000c151367"
+    "6ac3bd7fea000300076c6f000004000e69665f6f6374657473000006001800020202000000"
+    "000009e79c000000000009e79c0008000c1513676ac3bdaae60003000a776c616e30000006"
+    "001800020202000000001009fa5400000000011cf6670008000c1513676ac3bdb0e0000400"
+    "0e69665f6572726f7273000006001800020202000000000000000000000000000000000008"
+    "000c1513676ac3bd3d6d0003000965746830000004000f69665f7061636b65747300000600"
+    "1800020202000000000000000000000000000000000008000c1513676ac3bdae290003000a"
+    "776c616e300000060018000202020000000000032f8f00000000000205e50008000c151367"
+    "6ac3bdbb7b0003000c646f636b657230000006001800020202000000000000000000000000"
+    "000000000008000c1513676ac3bda0db000300076c6f000004000e69665f6572726f727300"
+    "0006001800020202000000000000000000000000000000000008000c1513676ac3bdbde800"
+    "03000c646f636b657230000006001800020202000000000000000000000000000000000008"
+    "000c1513676ac3bd8d8e000300076c6f000004000f69665f7061636b657473000006001800"
+    "0202020000000000000c9c0000000000000c9c0008000c1513676ac3bdb90b0003000c646f"
+    "636b657230000004000e69665f6f6374657473000006001800020202000000000000000000"
+    "000000000000000008000c1513676ac469b10f0002000e70726f6365737365730000030005"
+    "000004000d70735f7374617465000005000c7a6f6d62696573000006000f00010100000000"
+    "000000000008000c1513676ac469a4a30005000d736c656570696e67000006000f00010100"
+    "00000000006e400008000c1513676ac469c6320005000b706167696e67000006000f000101"
+    "00000000000000000008000c1513676ac469f06e0005000c626c6f636b6564000006000f00"
+    "010100000000000000000008000c1513676ac4698af40005000c72756e6e696e6700000600"
+    "0f00010100000000000000000008000c1513676ac469bbe10005000c73746f707065640000"
+    "06000f00010100000000000000000008000c1513676ac46b8e710004000e666f726b5f7261"
+    "74650000050005000006000f0001020000000000001bcf0008000c1513676d437f12960002"
+    "00086370750000030006300000040008637075000005000b73797374656d000006000f0001"
+    "0200000000000021870008000c1513676d437f36020005000969646c65000006000f000102"
+    "000000000005847a0008000c1513676d437f979b0005000977616974000006000f00010200"
+    "000000000005210008000c1513676d43802ff60005000c736f6674697271000006000f0001"
+    "02000000000000001f0008000c1513676d43803b3a0005000a737465616c000006000f0001"
+    "020000000000000000",
+    "0000000e6c6f63616c686f7374000008000c1513676d4380551f0009000c00000002800000"
+    "00000200086370750000030006310000040008637075000005000975736572000006000f00"
+    "01020000000000007cad0008000c1513676d43805dbe000500096e696365000006000f0001"
+    "0200000000000001de0008000c1513676d4380697d0005000b73797374656d000006000f00"
+    "01020000000000001ce80008000c1513676d438072bd0005000969646c65000006000f0001"
+    "02000000000005931c0008000c1513676d43807c430005000977616974000006000f000102"
+    "000000000000094b0008000c1513676d43808cee0005000c736f6674697271000006000f00"
+    "010200000000000000120008000c1513676d4380843a0005000e696e746572727570740000"
+    "06000f00010200000000000000000008000c1513676d438096230005000a737465616c0000"
+    "06000f00010200000000000000000008000c1513676d4380aa9c0003000632000005000975"
+    "736572000006000f00010200000000000089580008000c1513676d4380b29f000500096e69"
+    "6365000006000f00010200000000000003610008000c1513676d4380c44c0005000969646c"
+    "65000006000f000102000000000005873d0008000c1513676d4380bc0f0005000b73797374"
+    "656d000006000f000102000000000000201d0008000c1513676d4380cea400050009776169"
+    "74000006000f00010200000000000005810008000c1513676d4380d7370005000e696e7465"
+    "7272757074000006000f00010200000000000000000008000c1513676d4380ea830005000a"
+    "737465616c000006000f00010200000000000000000008000c1513676d437eef6200030006"
+    "3000000500096e696365000006000f00010200000000000003920008000c1513676d4380e0"
+    "260003000632000005000c736f6674697271000006000f0001020000000000000016000800"
+    "0c1513676d438101410003000633000005000975736572000006000f000102000000000000"
+    "7d8a0008000c1513676d438109f5000500096e696365000006000f00010200000000000004"
+    "350008000c1513676d4380244b0003000630000005000e696e74657272757074000006000f"
+    "00010200000000000000000008000c1513676d438122070003000633000005000969646c65"
+    "000006000f0001020000000000058eb60008000c1513676d43812e83000500097761697400"
+    "0006000f0001020000000000000ca80008000c1513676d438141480005000c736f66746972"
+    "71000006000f000102000000000000001e0008000c1513676d43814a5d0005000a73746561"
+    "6c000006000f00010200000000000000000008000c1513676d4381149e0005000b73797374"
+    "656d000006000f0001020000000000001b9a0008000c1513676d437ea86000030006300000"
+    "05000975736572000006000f00010200000000000089a80008000c1513676d438138190003"
+    "000633000005000e696e74657272757074000006000f00010200000000000000000008000c"
+    "1513676d438a9ca00002000e696e74657266616365000003000965746830000004000e6966"
+    "5f6f6374657473000005000500000600180002020200000000000000000000000000000000"
+    "0008000c1513676d438aea760004000f69665f7061636b6574730000060018000202020000"
+    "00000000000000000000000000000008000c1513676d438b214d0004000e69665f6572726f"
+    "727300000600180002020200000000000000000000000000000000",
+    "0000000e6c6f63616c686f7374000008000c1513676d438aac590009000c00000002800000"
+    "000002000764660000030009726f6f74000004000f64665f636f6d706c6578000005000966"
+    "726565000006000f0001010000004c077e57420008000c1513676d438b6ada0005000d7265"
+    "736572766564000006000f00010100000000338116420008000c1513676d438b7a17000200"
+    "0e696e7465726661636500000300076c6f000004000e69665f6f6374657473000005000500"
+    "0006001800020202000000000009ecf5000000000009ecf50008000c1513676d438b757800"
+    "02000764660000030009726f6f74000004000f64665f636f6d706c65780000050009757365"
+    "64000006000f000101000000e0a41b26420008000c1513676d438b8ed20002000e696e7465"
+    "726661636500000300076c6f000004000e69665f6572726f72730000050005000006001800"
+    "020202000000000000000000000000000000000008000c1513676d438b86bf0004000f6966"
+    "5f7061636b6574730000060018000202020000000000000c9d0000000000000c9d0008000c"
+    "1513676d438bb3e60003000a776c616e300000060018000202020000000000032fab000000"
+    "00000205ed0008000c1513676d438bd62e0003000c646f636b657230000004000e69665f6f"
+    "6374657473000006001800020202000000000000000000000000000000000008000c151367"
+    "6d438bbc8f0003000a776c616e30000004000e69665f6572726f7273000006001800020202"
+    "000000000000000000000000000000000008000c1513676d438bdf030003000c646f636b65"
+    "7230000004000f69665f7061636b6574730000060018000202020000000000000000000000"
+    "00000000000008000c1513676d438baaf10003000a776c616e30000004000e69665f6f6374"
+    "65747300000600180002020200000000100a042300000000011cfa460008000c1513676d43"
+    "8c5f100002000764660000030009626f6f74000004000f64665f636f6d706c657800000500"
+    "0966726565000006000f0001010000000010e198410008000c1513676d438c689c0005000d"
+    "7265736572766564000006000f00010100000000804c68410008000c1513676d438c70ce00"
+    "05000975736564000006000f0001010000000020ea9e410008000c1513676d438be7bc0002"
+    "000e696e74657266616365000003000c646f636b657230000004000e69665f6572726f7273"
+    "0000050005000006001800020202000000000000000000000000000000000008000c151367"
+    "6d43beca8c0002000c656e74726f70790000030005000004000c656e74726f707900000600"
+    "0f0001010000000000088f400008000c1513676d43bf1d13000200096c6f61640000040009"
+    "6c6f6164000006002100030101019a9999999999a93f666666666666d63f5c8fc2f5285cdf"
+    "3f0008000c1513676d43c02b85000200096469736b00000300087364610000040010646973"
+    "6b5f6f63746574730000060018000202020000000075887800000000005b6f3c000008000c"
+    "1513676d43c06d1f0004000d6469736b5f6f7073000006001800020202000000000003cbbd"
+    "000000000001c0510008000c1513676d43c08b6a0004000e6469736b5f74696d6500000600"
+    "1800020202000000000000003f00000000000001720008000c1513676d43c0a5fb00040010"
+    "6469736b5f6d65726765640000060018000202020000000000001285000000000000f80100"
+    "08000c1513676d43c0c8b4000300097364613100000400106469736b5f6f63746574730000"
+    "060018000202020000000001107c000000000000003c00",
+    "0000000e6c6f63616c686f7374000008000c1513676d43c0d00a0009000c00000002800000"
+    "00000200096469736b000003000973646131000004000d6469736b5f6f7073000006001800"
+    "020202000000000000029b00000000000000080008000c1513676d43c0d7b20004000e6469"
+    "736b5f74696d650000060018000202020000000000000004000000000000000f0008000c15"
+    "13676d43c0df73000400106469736b5f6d6572676564000006001800020202000000000000"
+    "0fb400000000000000010008000c1513676d43c0f87c000300097364613200000400106469"
+    "736b5f6f637465747300000600180002020200000000000008000000000000000000000800"
+    "0c1513676d43c1003e0004000d6469736b5f6f707300000600180002020200000000000000"
+    "0200000000000000000008000c1513676d43c107bf000400106469736b5f6d657267656400"
+    "0006001800020202000000000000000000000000000000000008000c1513676d43c12fa400"
+    "03000973646135000004000d6469736b5f6f7073000006001800020202000000000003c867"
+    "000000000001aef20008000c1513676d43c13d5e000400106469736b5f6d65726765640000"
+    "0600180002020200000000000002d1000000000000f8000008000c1513676d43c136a90004"
+    "000e6469736b5f74696d65000006001800020202000000000000003f000000000000011c00"
+    "08000c1513676d43c1740500030009646d2d3000000400106469736b5f6f63746574730000"
+    "060018000202020000000074596400000000005b6f00000008000c1513676d43c179c70004"
+    "000d6469736b5f6f7073000006001800020202000000000003cae4000000000002b0f30008"
+    "000c1513676d43c18abe000400106469736b5f6d6572676564000006001800020202000000"
+    "000000000000000000000000000008000c1513676d43c181b90004000e6469736b5f74696d"
+    "650000060018000202020000000000000040000000000000013e0008000c1513676d43c1a9"
+    "5e00030009646d2d3100000400106469736b5f6f6374657473000006001800020202000000"
+    "00000e000000000000000000000008000c1513676d43c1b7ea0004000e6469736b5f74696d"
+    "65000006001800020202000000000000000200000000000000000008000c1513676d43c1b0"
+    "3e0004000d6469736b5f6f707300000600180002020200000000000000e000000000000000"
+    "000008000c1513676d43c1c00d000400106469736b5f6d6572676564000006001800020202"
+    "000000000000000000000000000000000008000c1513676d43c12818000300097364613500"
+    "000400106469736b5f6f637465747300000600180002020200000000746c6400000000005b"
+    "6f00000008000c1513676d43d320a80002000c62617474657279000003000630000004000b"
+    "636861726765000006000f0001018fc2f5285c2f58400008000c1513676d43d36fd6000400"
+    "0c63757272656e74000006000f00010100000000000000800008000c1513676d43d3cdb600"
+    "04000c766f6c74616765000006000f000101736891ed7cbf28400008000c1513676d43d59d"
+    "d60002000869727100000300050000040008697271000005000630000006000f0001020000"
+    "0000000000110008000c1513676d43d5d2cf0005000631000006000f000102000000000000"
+    "00100008000c1513676d43d5fe820005000638000006000f00010200000000000000010008"
+    "000c1513676d43d635440005000639000006000f00010200000000000035210008000c1513"
+    "676d43d66265000500073132000006000f0001020000000000000790",
+    "0000000e6c6f63616c686f7374000008000c1513676d43d68e940009000c00000002800000"
+    "0000020008697271000004000869727100000500073136000006000f000102000000000000"
+    "00210008000c1513676d43d69be20002000a7573657273000004000a757365727300000500"
+    "05000006000f00010100000000000010400008000c1513676d43d6aa5d0002000869727100"
+    "0004000869727100000500073233000006000f00010200000000000000250008000c151367"
+    "6d43d6c7dc000500073431000006000f000102000000000000ff7d0008000c1513676d43d6"
+    "e23d000500073432000006000f00010200000000000008070008000c1513676d43d9aa3a00"
+    "0500073437000006000f0001020000000000079a260008000c1513676d43d9cca900050007"
+    "3438000006000f00010200000000000000c70008000c1513676d43d9ea5d00050007343900"
+    "0006000f00010200000000000004c20008000c1513676d43da050e00050007353000000600"
+    "0f000102000000000000001c0008000c1513676d43da1efa000500084e4d49000006000f00"
+    "010200000000000000000008000c1513676d43da3c82000500084c4f43000006000f000102"
+    "000000000018d3080008000c1513676d43da544e00050008535055000006000f0001020000"
+    "0000000000000008000c1513676d43da6cca00050008504d49000006000f00010200000000"
+    "000000000008000c1513676d43da885400050008495749000006000f000102000000000000"
+    "a9da0008000c1513676d43daa23a00050008525452000006000f0001020000000000000003"
+    "0008000c1513676d43dabaed00050008524553000006000f00010200000000000ac8360008"
+    "000c1513676d43dad4150005000843414c000006000f000102000000000000191f0008000c"
+    "1513676d43daeef300050008544c42000006000f000102000000000003dbdc0008000c1513"
+    "676d43db11410005000854524d000006000f00010200000000000000000008000c1513676d"
+    "43db292c00050008544852000006000f00010200000000000000000008000c1513676d43db"
+    "411d000500084d4345000006000f00010200000000000000000008000c1513676d43db5b59"
+    "000500084d4350000006000f000102000000000000003c0008000c1513676d43db68010005"
+    "0008455252000006000f00010200000000000000000008000c1513676d43db758a00050008"
+    "4d4953000006000f00010200000000000000000008000c1513676d43dd2e800002000b6d65"
+    "6d6f7279000004000b6d656d6f7279000005000975736564000006000f00010100000000fe"
+    "bbe0410008000c1513676d43dd3f4b0005000d6275666665726564000006000f0001010000"
+    "000070fbc8410008000c1513676d43dd48700005000b636163686564000006000f00010100"
+    "000000c008df410008000c1513676d43dd51c60005000966726565000006000f0001010000"
+    "0080481d05420008000c1513676d43dec7e300020009737761700000040009737761700000"
+    "05000975736564000006000f00010100000000000000000008000c1513676d43ded4490005"
+    "000966726565000006000f00010100000080ff610f420008000c1513676d43dedcfd000500"
+    "0b636163686564000006000f00010100000000000000000008000c1513676d43d715e30002"
+    "0008697271000004000869727100000500073434000006000f0001020000000000031b6100"
+    "08000c1513676d43d73116000500073435000006000f00010200000000000000180008000c"
+    "1513676d43ee00150002000973776170000004000c737761705f696f0000050007696e0000"
+    "06000f0001020000000000000000",
+};
+
+static int decode_string(char const *in, uint8_t *out, size_t *out_size) {
+  size_t in_size = strlen(in);
+  if (*out_size < (in_size / 2))
+    return -1;
+  *out_size = in_size / 2;
+
+  for (size_t i = 0; i < *out_size; i++) {
+    char tmp[] = {in[2 * i], in[2 * i + 1], 0};
+    out[i] = (uint8_t)strtoul(tmp, NULL, 16);
+  }
+
+  return 0;
+}
+
+DEF_TEST(parse_packet) {
+  sockent_t se = {
+      .data.server =
+          (struct sockent_server){
+#if HAVE_GCRYPT_H
+              .cypher = NULL,
+              .userdb = NULL,
+              .security_level = SECURITY_LEVEL_NONE,
+#endif
+          },
+  };
+
+  for (size_t i = 0; i < sizeof(raw_packet_data) / sizeof(raw_packet_data[0]);
+       i++) {
+    uint8_t buffer[network_config_packet_size];
+    size_t buffer_size = sizeof(buffer);
+
+    EXPECT_EQ_INT(0, decode_string(raw_packet_data[i], buffer, &buffer_size));
+    EXPECT_EQ_INT(0, parse_packet(&se, buffer, buffer_size, 0, NULL));
+  }
+  EXPECT_EQ_INT(139, (int)stats_values_dispatched);
+
+  return 0;
+}
+
+int main() {
+  RUN_TEST(parse_packet);
+
+  END_TEST;
+}
index 320caa4..97d9125 100644 (file)
--- a/src/nfs.c
+++ b/src/nfs.c
@@ -322,7 +322,7 @@ static int nfs_config(const char *key, const char *value) {
 
 #if KERNEL_LINUX
 static int nfs_init(void) { return 0; }
-/* #endif KERNEL_LINUX */
+  /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKSTAT
 static int nfs_init(void) {
@@ -594,7 +594,7 @@ static int nfs_read(void) {
 
   return 0;
 }
-/* #endif KERNEL_LINUX */
+  /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKSTAT
 static int nfs_read(void) {
index 7bb307a..0da66ce 100644 (file)
@@ -122,8 +122,8 @@ static int init(void) {
     curl_easy_setopt(curl, CURLOPT_PASSWORD, (pass == NULL) ? "" : pass);
 #else
     static char credentials[1024];
-    int status = snprintf(credentials, sizeof(credentials), "%s:%s", user,
-                          pass == NULL ? "" : pass);
+    int status = ssnprintf(credentials, sizeof(credentials), "%s:%s", user,
+                           pass == NULL ? "" : pass);
     if ((status < 0) || ((size_t)status >= sizeof(credentials))) {
       ERROR("nginx plugin: Credentials would have been truncated.");
       return -1;
index 849b1d4..e430b68 100644 (file)
@@ -93,16 +93,16 @@ static int c_notify(const notification_t *n,
     timeout = fail_timeout;
   }
 
-  snprintf(summary, sizeof(summary), "collectd %s notification",
-           (NOTIF_FAILURE == n->severity)
-               ? "FAILURE"
-               : (NOTIF_WARNING == n->severity)
-                     ? "WARNING"
-                     : (NOTIF_OKAY == n->severity) ? "OKAY" : "UNKNOWN");
+  ssnprintf(summary, sizeof(summary), "collectd %s notification",
+            (NOTIF_FAILURE == n->severity)
+                ? "FAILURE"
+                : (NOTIF_WARNING == n->severity)
+                      ? "WARNING"
+                      : (NOTIF_OKAY == n->severity) ? "OKAY" : "UNKNOWN");
 
   notification = notify_notification_new(summary, n->message, NULL
 #if NOTIFY_CHECK_VERSION(0, 7, 0)
-                                         );
+  );
 #else
                                          ,
                                          NULL);
index dddb8b2..0e140e4 100644 (file)
@@ -104,8 +104,8 @@ static void monitor_cb(const char *buf, int buflen, int writing,
 static int notify_email_init(void) {
   char server[MAXSTRING];
 
-  snprintf(server, sizeof(server), "%s:%i",
-           (smtp_host == NULL) ? DEFAULT_SMTP_HOST : smtp_host, smtp_port);
+  ssnprintf(server, sizeof(server), "%s:%i",
+            (smtp_host == NULL) ? DEFAULT_SMTP_HOST : smtp_host, smtp_port);
 
   pthread_mutex_lock(&session_lock);
 
@@ -214,16 +214,16 @@ static int notify_email_notification(const notification_t *n,
   char *buf_ptr = buf;
   int buf_len = sizeof(buf);
 
-  snprintf(severity, sizeof(severity), "%s",
-           (n->severity == NOTIF_FAILURE)
-               ? "FAILURE"
-               : ((n->severity == NOTIF_WARNING)
-                      ? "WARNING"
-                      : ((n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN")));
+  ssnprintf(severity, sizeof(severity), "%s",
+            (n->severity == NOTIF_FAILURE)
+                ? "FAILURE"
+                : ((n->severity == NOTIF_WARNING)
+                       ? "WARNING"
+                       : ((n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN")));
 
-  snprintf(subject, sizeof(subject),
-           (email_subject == NULL) ? DEFAULT_SMTP_SUBJECT : email_subject,
-           severity, n->host);
+  ssnprintf(subject, sizeof(subject),
+            (email_subject == NULL) ? DEFAULT_SMTP_SUBJECT : email_subject,
+            severity, n->host);
 
   localtime_r(&CDTIME_T_TO_TIME_T(n->time), &timestamp_tm);
   strftime(timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S",
@@ -231,15 +231,15 @@ static int notify_email_notification(const notification_t *n,
   timestamp_str[sizeof(timestamp_str) - 1] = '\0';
 
   /* Let's make RFC822 message text with \r\n EOLs */
-  int status = snprintf(buf, buf_len,
-                        "MIME-Version: 1.0\r\n"
-                        "Content-Type: text/plain; charset=\"US-ASCII\"\r\n"
-                        "Content-Transfer-Encoding: 8bit\r\n"
-                        "Subject: %s\r\n"
-                        "\r\n"
-                        "%s - %s@%s\r\n"
-                        "\r\n",
-                        subject, timestamp_str, severity, n->host);
+  int status = ssnprintf(buf, buf_len,
+                         "MIME-Version: 1.0\r\n"
+                         "Content-Type: text/plain; charset=\"US-ASCII\"\r\n"
+                         "Content-Transfer-Encoding: 8bit\r\n"
+                         "Subject: %s\r\n"
+                         "\r\n"
+                         "%s - %s@%s\r\n"
+                         "\r\n",
+                         subject, timestamp_str, severity, n->host);
 
   if (status > 0) {
     buf_ptr += status;
@@ -248,7 +248,7 @@ static int notify_email_notification(const notification_t *n,
 
 #define APPEND(format, value)                                                  \
   if ((buf_len > 0) && (strlen(value) > 0)) {                                  \
-    status = snprintf(buf_ptr, buf_len, format "\r\n", value);                 \
+    status = ssnprintf(buf_ptr, buf_len, format "\r\n", value);                \
     if (status > 0) {                                                          \
       buf_ptr += status;                                                       \
       buf_len -= status;                                                       \
index ae48692..552359e 100644 (file)
--- a/src/nut.c
+++ b/src/nut.c
@@ -100,8 +100,10 @@ static int nut_add_ups(const char *name) {
       /* name      = */ cb_name,
       /* callback  = */ nut_read,
       /* interval  = */ 0,
-      /* user_data = */ &(user_data_t){
-          .data = ups, .free_func = free_nut_ups_t,
+      /* user_data = */
+      &(user_data_t){
+          .data = ups,
+          .free_func = free_nut_ups_t,
       });
 
   sfree(cb_name);
index a0a546b..729a05c 100644 (file)
@@ -297,8 +297,8 @@ static int cow_read_values(const char *path, const char *name,
     char file[4096];
     char *endptr;
 
-    snprintf(file, sizeof(file), "%s/%s", path,
-             family_info->features[i].filename);
+    ssnprintf(file, sizeof(file), "%s/%s", path,
+              family_info->features[i].filename);
     file[sizeof(file) - 1] = '\0';
 
     buffer = NULL;
@@ -348,11 +348,11 @@ static int cow_read_ds2409(const char *path) {
   char subpath[4096];
   int status;
 
-  status = snprintf(subpath, sizeof(subpath), "%s/main", path);
+  status = ssnprintf(subpath, sizeof(subpath), "%s/main", path);
   if ((status > 0) && (status < (int)sizeof(subpath)))
     cow_read_bus(subpath);
 
-  status = snprintf(subpath, sizeof(subpath), "%s/aux", path);
+  status = ssnprintf(subpath, sizeof(subpath), "%s/aux", path);
   if ((status > 0) && (status < (int)sizeof(subpath)))
     cow_read_bus(subpath);
 
@@ -384,9 +384,9 @@ static int cow_read_bus(const char *path) {
     dummy = NULL;
 
     if (strcmp("/", path) == 0)
-      status = snprintf(subpath, sizeof(subpath), "/%s", buffer_ptr);
+      status = ssnprintf(subpath, sizeof(subpath), "/%s", buffer_ptr);
     else
-      status = snprintf(subpath, sizeof(subpath), "%s/%s", path, buffer_ptr);
+      status = ssnprintf(subpath, sizeof(subpath), "%s/%s", path, buffer_ptr);
     if ((status <= 0) || (status >= (int)sizeof(subpath)))
       continue;
 
index 5659c69..cd72cdb 100644 (file)
@@ -306,8 +306,8 @@ static int cldap_read_host(user_data_t *ud) /* {{{ */
         if ((olmbdb_list =
                  ldap_get_values_len(st->ld, e, "olmBDBEntryCache")) != NULL) {
           olmbdb_data = *olmbdb_list[0];
-          snprintf(typeinst, sizeof(typeinst), "bdbentrycache-%s",
-                   nc_data.bv_val);
+          ssnprintf(typeinst, sizeof(typeinst), "bdbentrycache-%s",
+                    nc_data.bv_val);
           cldap_submit_gauge("cache_size", typeinst, atoll(olmbdb_data.bv_val),
                              st);
           ldap_value_free_len(olmbdb_list);
@@ -316,7 +316,8 @@ static int cldap_read_host(user_data_t *ud) /* {{{ */
         if ((olmbdb_list = ldap_get_values_len(st->ld, e, "olmBDBDNCache")) !=
             NULL) {
           olmbdb_data = *olmbdb_list[0];
-          snprintf(typeinst, sizeof(typeinst), "bdbdncache-%s", nc_data.bv_val);
+          ssnprintf(typeinst, sizeof(typeinst), "bdbdncache-%s",
+                    nc_data.bv_val);
           cldap_submit_gauge("cache_size", typeinst, atoll(olmbdb_data.bv_val),
                              st);
           ldap_value_free_len(olmbdb_list);
@@ -325,8 +326,8 @@ static int cldap_read_host(user_data_t *ud) /* {{{ */
         if ((olmbdb_list = ldap_get_values_len(st->ld, e, "olmBDBIDLCache")) !=
             NULL) {
           olmbdb_data = *olmbdb_list[0];
-          snprintf(typeinst, sizeof(typeinst), "bdbidlcache-%s",
-                   nc_data.bv_val);
+          ssnprintf(typeinst, sizeof(typeinst), "bdbidlcache-%s",
+                    nc_data.bv_val);
           cldap_submit_gauge("cache_size", typeinst, atoll(olmbdb_data.bv_val),
                              st);
           ldap_value_free_len(olmbdb_list);
@@ -462,16 +463,17 @@ static int cldap_config_add(oconfig_item_t *ci) /* {{{ */
 
   char callback_name[3 * DATA_MAX_NAME_LEN] = {0};
 
-  snprintf(callback_name, sizeof(callback_name), "openldap/%s/%s",
-           (st->host != NULL) ? st->host : hostname_g,
-           (st->name != NULL) ? st->name : "default");
+  ssnprintf(callback_name, sizeof(callback_name), "openldap/%s/%s",
+            (st->host != NULL) ? st->host : hostname_g,
+            (st->name != NULL) ? st->name : "default");
 
   return plugin_register_complex_read(/* group = */ NULL,
                                       /* name      = */ callback_name,
                                       /* callback  = */ cldap_read_host,
                                       /* interval  = */ 0,
                                       &(user_data_t){
-                                          .data = st, .free_func = cldap_free,
+                                          .data = st,
+                                          .free_func = cldap_free,
                                       });
 } /* }}} int cldap_config_add */
 
index 4d4a878..b0e4bf4 100644 (file)
@@ -139,7 +139,8 @@ static void iostats_submit(const char *pinst, const char *tinst, derive_t rx,
                            derive_t tx) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = rx}, {.derive = tx},
+      {.derive = rx},
+      {.derive = tx},
   };
 
   /* NOTE ON THE NEW NAMING SCHEMA:
@@ -165,7 +166,8 @@ static void compression_submit(const char *pinst, const char *tinst,
                                derive_t uncompressed, derive_t compressed) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = uncompressed}, {.derive = compressed},
+      {.derive = uncompressed},
+      {.derive = compressed},
   };
 
   vl.values = values;
@@ -502,14 +504,15 @@ static int openvpn_config(const char *key, const char *value) {
         /* callback  = */ openvpn_read,
         /* interval  = */ 0,
         &(user_data_t){
-            .data = instance, .free_func = openvpn_free,
+            .data = instance,
+            .free_func = openvpn_free,
         });
 
     if (status == EINVAL) {
-      WARNING("openvpn plugin: status filename \"%s\" "
-              "already used, please choose a "
-              "different one.",
-              status_name);
+      ERROR("openvpn plugin: status filename \"%s\" "
+            "already used, please choose a "
+            "different one.",
+            status_name);
       return -1;
     }
 
index 3f28110..cebc7a2 100644 (file)
@@ -640,7 +640,7 @@ static int o_read_database(o_database_t *db) /* {{{ */
     if ((status != OCI_SUCCESS) && (status != OCI_SUCCESS_WITH_INFO)) {
       char errfunc[256];
 
-      snprintf(errfunc, sizeof(errfunc), "OCILogon(\"%s\")", db->connect_id);
+      ssnprintf(errfunc, sizeof(errfunc), "OCILogon(\"%s\")", db->connect_id);
 
       o_report_error("o_read_database", db->name, NULL, errfunc, oci_error);
       DEBUG("oracle plugin: OCILogon (%s): db->oci_service_context = %p;",
index 0f9a57c..ae8ac3d 100644 (file)
@@ -158,8 +158,8 @@ static char *ovs_events_get_select_params() {
       return NULL;
     }
     opt_buff = new_buff;
-    int ret = snprintf(opt_buff + buff_off, buff_size - buff_off, option_fmt,
-                       iface->name);
+    int ret = ssnprintf(opt_buff + buff_off, buff_size - buff_off, option_fmt,
+                        iface->name);
     if (ret < 0) {
       sfree(opt_buff);
       return NULL;
@@ -339,9 +339,9 @@ ovs_events_dispatch_notification(const ovs_events_iface_info_t *ifinfo) {
   }
 
   /* fill the notification data */
-  snprintf(n.message, sizeof(n.message),
-           "link state of \"%s\" interface has been changed to \"%s\"",
-           ifinfo->name, msg_link_status);
+  ssnprintf(n.message, sizeof(n.message),
+            "link state of \"%s\" interface has been changed to \"%s\"",
+            ifinfo->name, msg_link_status);
   sstrncpy(n.host, hostname_g, sizeof(n.host));
   sstrncpy(n.plugin_instance, ifinfo->name, sizeof(n.plugin_instance));
   sstrncpy(n.type, "gauge", sizeof(n.type));
index da218b6..e22e851 100644 (file)
@@ -282,7 +282,9 @@ static void ovs_stats_submit_interfaces(port_list_t *port) {
     }
     strjoin(devname, sizeof(devname),
             (char *[]){
-                bridge->name, port->name, iface->name,
+                bridge->name,
+                port->name,
+                iface->name,
             },
             3, ".");
     ovs_stats_submit_one(devname, "if_collisions", NULL,
@@ -394,16 +396,16 @@ static void ovs_stats_submit_port(port_list_t *port) {
 
     for (interface_list_t *iface = port->iface; iface != NULL;
          iface = iface->next) {
-      snprintf(key_str, sizeof(key_str), "uuid%d", i);
+      ssnprintf(key_str, sizeof(key_str), "uuid%d", i);
       meta_data_add_string(meta, key_str, iface->iface_uuid);
 
       if (strlen(iface->ex_vm_id)) {
-        snprintf(key_str, sizeof(key_str), "vm-uuid%d", i);
+        ssnprintf(key_str, sizeof(key_str), "vm-uuid%d", i);
         meta_data_add_string(meta, key_str, iface->ex_vm_id);
       }
 
       if (strlen(iface->ex_iface_id)) {
-        snprintf(key_str, sizeof(key_str), "iface-id%d", i);
+        ssnprintf(key_str, sizeof(key_str), "iface-id%d", i);
         meta_data_add_string(meta, key_str, iface->ex_iface_id);
       }
 
@@ -411,7 +413,7 @@ static void ovs_stats_submit_port(port_list_t *port) {
     }
   }
   bridge_list_t *bridge = port->br;
-  snprintf(devname, sizeof(devname), "%s.%s", bridge->name, port->name);
+  ssnprintf(devname, sizeof(devname), "%s.%s", bridge->name, port->name);
   ovs_stats_submit_one(devname, "if_collisions", NULL,
                        ovs_stats_get_port_stat_value(port, collisions), meta);
   ovs_stats_submit_two(devname, "if_dropped", NULL,
index 6399605..b7282ea 100644 (file)
@@ -492,7 +492,7 @@ static void pcie_dispatch_uncorrectable_errors(pcie_device_t *dev,
 /* Find offset of PCI Express Capability Structure
  * in PCI configuration space.
  * Returns offset, -1 if not found.
-**/
+ **/
 static int pcie_find_cap_exp(pcie_device_t *dev) {
   int pos = pcie_read8(dev, PCI_CAPABILITY_LIST) & ~3;
 
@@ -515,7 +515,7 @@ static int pcie_find_cap_exp(pcie_device_t *dev) {
 
 /* Find offset of Advanced Error Reporting Capability.
  * Returns AER offset, -1 if not found.
-**/
+ **/
 static int pcie_find_ecap_aer(pcie_device_t *dev) {
   int pos = PCIE_ECAP_OFFSET;
   uint32_t header = pcie_read32(dev, pos);
index 09e6e5a..0a4ae71 100644 (file)
@@ -863,9 +863,9 @@ static int oconfig_item2hv(pTHX_ oconfig_item_t *ci, HV *hash) {
 static char *get_module_name(char *buf, size_t buf_len, const char *module) {
   int status = 0;
   if (base_name[0] == '\0')
-    status = snprintf(buf, buf_len, "%s", module);
+    status = ssnprintf(buf, buf_len, "%s", module);
   else
-    status = snprintf(buf, buf_len, "%s::%s", base_name, module);
+    status = ssnprintf(buf, buf_len, "%s::%s", base_name, module);
   if ((status < 0) || ((unsigned int)status >= buf_len))
     return NULL;
   return buf;
index 8e4328f..4e608be 100644 (file)
@@ -58,7 +58,7 @@
  * is ignored. */
 #define C_PSQL_PAR_APPEND(buf, buf_len, parameter, value)                      \
   if ((0 < (buf_len)) && (NULL != (value)) && ('\0' != *(value))) {            \
-    int s = snprintf(buf, buf_len, " %s = '%s'", parameter, value);            \
+    int s = ssnprintf(buf, buf_len, " %s = '%s'", parameter, value);           \
     if (0 < s) {                                                               \
       buf += s;                                                                \
       buf_len -= s;                                                            \
@@ -323,7 +323,7 @@ static int c_psql_connect(c_psql_database_t *db) {
   if ((!db) || (!db->database))
     return -1;
 
-  status = snprintf(buf, buf_len, "dbname = '%s'", db->database);
+  status = ssnprintf(buf, buf_len, "dbname = '%s'", db->database);
   if (0 < status) {
     buf += status;
     buf_len -= status;
@@ -426,8 +426,8 @@ static PGresult *c_psql_exec_query_params(c_psql_database_t *db, udb_query_t *q,
       params[i] = db->user;
       break;
     case C_PSQL_PARAM_INTERVAL:
-      snprintf(interval, sizeof(interval), "%.3f",
-               CDTIME_T_TO_DOUBLE(plugin_get_interval()));
+      ssnprintf(interval, sizeof(interval), "%.3f",
+                CDTIME_T_TO_DOUBLE(plugin_get_interval()));
       params[i] = interval;
       break;
     case C_PSQL_PARAM_INSTANCE:
@@ -632,7 +632,7 @@ static char *values_name_to_sqlarray(const data_set_t *ds, char *string,
   str_len = string_len;
 
   for (size_t i = 0; i < ds->ds_num; ++i) {
-    int status = snprintf(str_ptr, str_len, ",'%s'", ds->ds[i].name);
+    int status = ssnprintf(str_ptr, str_len, ",'%s'", ds->ds[i].name);
 
     if (status < 1)
       return NULL;
@@ -670,10 +670,10 @@ static char *values_type_to_sqlarray(const data_set_t *ds, char *string,
     int status;
 
     if (store_rates)
-      status = snprintf(str_ptr, str_len, ",'gauge'");
+      status = ssnprintf(str_ptr, str_len, ",'gauge'");
     else
-      status = snprintf(str_ptr, str_len, ",'%s'",
-                        DS_TYPE_TO_STRING(ds->ds[i].type));
+      status = ssnprintf(str_ptr, str_len, ",'%s'",
+                         DS_TYPE_TO_STRING(ds->ds[i].type));
 
     if (status < 1) {
       str_len = 0;
@@ -725,7 +725,7 @@ static char *values_to_sqlarray(const data_set_t *ds, const value_list_t *vl,
 
     if (ds->ds[i].type == DS_TYPE_GAUGE)
       status =
-          snprintf(str_ptr, str_len, "," GAUGE_FORMAT, vl->values[i].gauge);
+          ssnprintf(str_ptr, str_len, "," GAUGE_FORMAT, vl->values[i].gauge);
     else if (store_rates) {
       if (rates == NULL)
         rates = uc_get_rate(ds, vl);
@@ -735,14 +735,14 @@ static char *values_to_sqlarray(const data_set_t *ds, const value_list_t *vl,
         return NULL;
       }
 
-      status = snprintf(str_ptr, str_len, ",%lf", rates[i]);
+      status = ssnprintf(str_ptr, str_len, ",%lf", rates[i]);
     } else if (ds->ds[i].type == DS_TYPE_COUNTER)
-      status = snprintf(str_ptr, str_len, ",%" PRIu64,
-                        (uint64_t)vl->values[i].counter);
+      status = ssnprintf(str_ptr, str_len, ",%" PRIu64,
+                         (uint64_t)vl->values[i].counter);
     else if (ds->ds[i].type == DS_TYPE_DERIVE)
-      status = snprintf(str_ptr, str_len, ",%" PRIi64, vl->values[i].derive);
+      status = ssnprintf(str_ptr, str_len, ",%" PRIi64, vl->values[i].derive);
     else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
-      status = snprintf(str_ptr, str_len, ",%" PRIu64, vl->values[i].absolute);
+      status = ssnprintf(str_ptr, str_len, ",%" PRIu64, vl->values[i].absolute);
 
     if (status < 1) {
       str_len = 0;
@@ -940,7 +940,7 @@ static int c_psql_shutdown(void) {
 
     if (db->writers_num > 0) {
       char cb_name[DATA_MAX_NAME_LEN];
-      snprintf(cb_name, sizeof(cb_name), "postgresql-%s", db->database);
+      ssnprintf(cb_name, sizeof(cb_name), "postgresql-%s", db->database);
 
       if (!had_flush) {
         plugin_unregister_flush("postgresql");
@@ -1199,7 +1199,7 @@ static int c_psql_config_database(oconfig_item_t *ci) {
     }
   }
 
-  snprintf(cb_name, sizeof(cb_name), "postgresql-%s", db->instance);
+  ssnprintf(cb_name, sizeof(cb_name), "postgresql-%s", db->instance);
 
   user_data_t ud = {.data = db, .free_func = c_psql_database_delete};
 
index a5b45a1..9079719 100644 (file)
@@ -89,48 +89,48 @@ all-outqueries        counts the number of outgoing UDP queries since starting
 answers-slow          counts the number of queries answered after 1 second
 answers0-1            counts the number of queries answered within 1 millisecond
 answers1-10           counts the number of queries answered within 10
-milliseconds
+                      milliseconds
 answers10-100         counts the number of queries answered within 100
-milliseconds
+                      milliseconds
 answers100-1000       counts the number of queries answered within 1 second
 cache-bytes           size of the cache in bytes (since 3.3.1)
 cache-entries         shows the number of entries in the cache
 cache-hits            counts the number of cache hits since starting, this does
-not include hits that got answered from the packet-cache
+                      not include hits that got answered from the packet-cache
 cache-misses          counts the number of cache misses since starting
 case-mismatches       counts the number of mismatches in character case since
-starting
+                      starting
 chain-resends         number of queries chained to existing outstanding query
 client-parse-errors   counts number of client packets that could not be parsed
 concurrent-queries    shows the number of MThreads currently running
 dlg-only-drops        number of records dropped because of delegation only
-setting
+                      setting
 dont-outqueries       number of outgoing queries dropped because of 'dont-query'
-setting (since 3.3)
+                      setting (since 3.3)
 edns-ping-matches     number of servers that sent a valid EDNS PING respons
 edns-ping-mismatches  number of servers that sent an invalid EDNS PING response
 failed-host-entries   number of servers that failed to resolve
 ipv6-outqueries       number of outgoing queries over IPv6
 ipv6-questions        counts all End-user initiated queries with the RD bit set,
-received over IPv6 UDP
+                      received over IPv6 UDP
 malloc-bytes          returns the number of bytes allocated by the process
-(broken, always returns 0)
+                      (broken, always returns 0)
 max-mthread-stack     maximum amount of thread stack ever used
 negcache-entries      shows the number of entries in the Negative answer cache
 no-packet-error       number of errorneous received packets
 noedns-outqueries     number of queries sent out without EDNS
 noerror-answers       counts the number of times it answered NOERROR since
-starting
+                      starting
 noping-outqueries     number of queries sent out without ENDS PING
 nsset-invalidations   number of times an nsset was dropped because it no longer
-worked
+                      worked
 nsspeeds-entries      shows the number of entries in the NS speeds map
 nxdomain-answers      counts the number of times it answered NXDOMAIN since
-starting
+                      starting
 outgoing-timeouts     counts the number of timeouts on outgoing UDP queries
-since starting
+                      since starting
 over-capacity-drops   questions dropped because over maximum concurrent query
-limit (since 3.2)
+                      limit (since 3.2)
 packetcache-bytes     size of the packet cache in bytes (since 3.3.1)
 packetcache-entries   size of packet cache (since 3.2)
 packetcache-hits      packet cache hits (since 3.2)
@@ -139,32 +139,32 @@ policy-drops          packets dropped because of (Lua) policy decision
 qa-latency            shows the current latency average
 questions             counts all end-user initiated queries with the RD bit set
 resource-limits       counts number of queries that could not be performed
-because of resource limits
+                      because of resource limits
 security-status       security status based on security polling
 server-parse-errors   counts number of server replied packets that could not be
-parsed
+                      parsed
 servfail-answers      counts the number of times it answered SERVFAIL since
-starting
+                      starting
 spoof-prevents        number of times PowerDNS considered itself spoofed, and
-dropped the data
+                      dropped the data
 sys-msec              number of CPU milliseconds spent in 'system' mode
 tcp-client-overflow   number of times an IP address was denied TCP access
-because it already had too many connections
+                      because it already had too many connections
 tcp-clients           counts the number of currently active TCP/IP clients
 tcp-outqueries        counts the number of outgoing TCP queries since starting
 tcp-questions         counts all incoming TCP queries (since starting)
 throttle-entries      shows the number of entries in the throttle map
 throttled-out         counts the number of throttled outgoing UDP queries since
-starting
+                      starting
 throttled-outqueries  idem to throttled-out
 unauthorized-tcp      number of TCP questions denied because of allow-from
-restrictions
+                      restrictions
 unauthorized-udp      number of UDP questions denied because of allow-from
-restrictions
+                      restrictions
 unexpected-packets    number of answers from remote servers that were unexpected
-(might point to spoofing)
+                      (might point to spoofing)
 unreachables          number of times nameservers were unreachable since
-starting
+                      starting
 uptime                number of seconds process has been running (since 3.1.5)
 user-msec             number of CPU milliseconds spent in 'user' mode
 }}} */
@@ -301,6 +301,7 @@ static statname_lookup_t lookup_table[] = /* {{{ */
         {"unauthorized-tcp", "counter", "denied-unauthorized_tcp"},
         {"unauthorized-udp", "counter", "denied-unauthorized_udp"},
         {"unexpected-packets", "dns_answer", "unexpected"},
+        {"unreachables", "counter", "unreachables"},
         {"uptime", "uptime", NULL}}; /* }}} */
 static int lookup_table_length = STATIC_ARRAY_SIZE(lookup_table);
 
index ac5ec60..4761f60 100644 (file)
@@ -757,7 +757,7 @@ static int ps_init(void) {
     pset_list_len = 0;
     return -1;
   }
-/* #endif HAVE_THREAD_INFO */
+    /* #endif HAVE_THREAD_INFO */
 
 #elif KERNEL_LINUX
   pagesize_g = sysconf(_SC_PAGESIZE);
@@ -771,13 +771,13 @@ static int ps_init(void) {
     }
   }
 #endif
-/* #endif KERNEL_LINUX */
+    /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKVM_GETPROCS &&                                                  \
     (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD)
   pagesize = getpagesize();
-/* #endif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD ||
- * HAVE_STRUCT_KINFO_PROC_OPENBSD) */
+  /* #endif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD ||
  * HAVE_STRUCT_KINFO_PROC_OPENBSD) */
 
 #elif HAVE_PROCINFO_H
   pagesize = getpagesize();
@@ -1316,11 +1316,10 @@ static int ps_read_process(long pid, process_entry_t *ps, char *state) {
 
   snprintf(filename, sizeof(filename), "/proc/%li/stat", pid);
 
-  status = read_file_contents(filename, buffer, sizeof(buffer) - 1);
+  status = read_text_file_contents(filename, buffer, sizeof(buffer));
   if (status <= 0)
     return -1;
   buffer_len = (size_t)status;
-  buffer[buffer_len] = 0;
 
   /* The name of the process is enclosed in parens. Since the name can
    * contain parens itself, spaces, numbers and pretty much everything
@@ -1569,7 +1568,7 @@ static char *ps_get_cmdline(long pid,
 
   snprintf(path, sizeof(path), "/proc/%li/psinfo", pid);
 
-  status = read_file_contents(path, (void *)&info, sizeof(info));
+  status = read_file_contents(path, &info, sizeof(info));
   if ((status < 0) || (((size_t)status) != sizeof(info))) {
     ERROR("processes plugin: Unexpected return value "
           "while reading \"%s\": "
@@ -1681,7 +1680,7 @@ static int ps_read_process(long pid, process_entry_t *ps, char *state) {
 
   /*
    * TODO: context switch counters for Solaris
-*/
+   */
   ps->cswitch_vol = -1;
   ps->cswitch_invol = -1;
 
@@ -2013,7 +2012,7 @@ static int ps_read(void) {
 
   for (ps = list_head_g; ps != NULL; ps = ps->next)
     ps_submit_proc_list(ps);
-/* #endif HAVE_THREAD_INFO */
+    /* #endif HAVE_THREAD_INFO */
 
 #elif KERNEL_LINUX
   int running = 0;
@@ -2095,7 +2094,7 @@ static int ps_read(void) {
     ps_submit_proc_list(ps_ptr);
 
   read_fork_rate();
-/* #endif KERNEL_LINUX */
+  /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD
   int running = 0;
@@ -2250,7 +2249,7 @@ static int ps_read(void) {
 
   for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
     ps_submit_proc_list(ps_ptr);
-/* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
+    /* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
 
 #elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_OPENBSD
   int running = 0;
@@ -2394,7 +2393,7 @@ static int ps_read(void) {
 
   for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
     ps_submit_proc_list(ps_ptr);
-/* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_OPENBSD */
+    /* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_OPENBSD */
 
 #elif HAVE_PROCINFO_H
   /* AIX */
@@ -2533,7 +2532,7 @@ static int ps_read(void) {
 
   for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
     ps_submit_proc_list(ps);
-/* #endif HAVE_PROCINFO_H */
+    /* #endif HAVE_PROCINFO_H */
 
 #elif KERNEL_SOLARIS
   /*
diff --git a/src/procevent.c b/src/procevent.c
new file mode 100644 (file)
index 0000000..ab000db
--- /dev/null
@@ -0,0 +1,1303 @@
+/**
+ * collectd - src/procevent.c
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Red Hat NFVPE
+ *     Andrew Bays <abays at redhat.com>
+ **/
+
+#include "collectd.h"
+
+#include "plugin.h"
+#include "utils/common/common.h"
+#include "utils/ignorelist/ignorelist.h"
+#include "utils_complain.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <dirent.h>
+#include <linux/cn_proc.h>
+#include <linux/connector.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <yajl/yajl_common.h>
+#include <yajl/yajl_gen.h>
+#if HAVE_YAJL_YAJL_VERSION_H
+#include <yajl/yajl_version.h>
+#endif
+#if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1)
+#define HAVE_YAJL_V2 1
+#endif
+
+#define PROCEVENT_EXITED 0
+#define PROCEVENT_STARTED 1
+#define PROCEVENT_FIELDS 3 // pid, status, timestamp
+#define BUFSIZE 512
+#define PROCDIR "/proc"
+#define RBUF_PROC_ID_INDEX 0
+#define RBUF_PROC_STATUS_INDEX 1
+#define RBUF_TIME_INDEX 2
+
+#define PROCEVENT_DOMAIN_FIELD "domain"
+#define PROCEVENT_DOMAIN_VALUE "fault"
+#define PROCEVENT_EVENT_ID_FIELD "eventId"
+#define PROCEVENT_EVENT_NAME_FIELD "eventName"
+#define PROCEVENT_EVENT_NAME_DOWN_VALUE "down"
+#define PROCEVENT_EVENT_NAME_UP_VALUE "up"
+#define PROCEVENT_LAST_EPOCH_MICROSEC_FIELD "lastEpochMicrosec"
+#define PROCEVENT_PRIORITY_FIELD "priority"
+#define PROCEVENT_PRIORITY_VALUE "high"
+#define PROCEVENT_REPORTING_ENTITY_NAME_FIELD "reportingEntityName"
+#define PROCEVENT_REPORTING_ENTITY_NAME_VALUE "collectd procevent plugin"
+#define PROCEVENT_SEQUENCE_FIELD "sequence"
+#define PROCEVENT_SEQUENCE_VALUE "0"
+#define PROCEVENT_SOURCE_NAME_FIELD "sourceName"
+#define PROCEVENT_START_EPOCH_MICROSEC_FIELD "startEpochMicrosec"
+#define PROCEVENT_VERSION_FIELD "version"
+#define PROCEVENT_VERSION_VALUE "1.0"
+
+#define PROCEVENT_ALARM_CONDITION_FIELD "alarmCondition"
+#define PROCEVENT_ALARM_INTERFACE_A_FIELD "alarmInterfaceA"
+#define PROCEVENT_EVENT_SEVERITY_FIELD "eventSeverity"
+#define PROCEVENT_EVENT_SEVERITY_CRITICAL_VALUE "CRITICAL"
+#define PROCEVENT_EVENT_SEVERITY_NORMAL_VALUE "NORMAL"
+#define PROCEVENT_EVENT_SOURCE_TYPE_FIELD "eventSourceType"
+#define PROCEVENT_EVENT_SOURCE_TYPE_VALUE "process"
+#define PROCEVENT_FAULT_FIELDS_FIELD "faultFields"
+#define PROCEVENT_FAULT_FIELDS_VERSION_FIELD "faultFieldsVersion"
+#define PROCEVENT_FAULT_FIELDS_VERSION_VALUE "1.0"
+#define PROCEVENT_SPECIFIC_PROBLEM_FIELD "specificProblem"
+#define PROCEVENT_SPECIFIC_PROBLEM_DOWN_VALUE "down"
+#define PROCEVENT_SPECIFIC_PROBLEM_UP_VALUE "up"
+#define PROCEVENT_VF_STATUS_FIELD "vfStatus"
+#define PROCEVENT_VF_STATUS_CRITICAL_VALUE "Ready to terminate"
+#define PROCEVENT_VF_STATUS_NORMAL_VALUE "Active"
+
+/*
+ * Private data types
+ */
+
+typedef struct {
+  int head;
+  int tail;
+  int maxLen;
+  cdtime_t **buffer;
+} circbuf_t;
+
+struct processlist_s {
+  char *process;
+
+  long pid;
+  int32_t last_status;
+
+  struct processlist_s *next;
+};
+typedef struct processlist_s processlist_t;
+
+/*
+ * Private variables
+ */
+static ignorelist_t *ignorelist = NULL;
+
+static int procevent_netlink_thread_loop = 0;
+static int procevent_netlink_thread_error = 0;
+static pthread_t procevent_netlink_thread_id;
+static int procevent_dequeue_thread_loop = 0;
+static pthread_t procevent_dequeue_thread_id;
+static pthread_mutex_t procevent_thread_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t procevent_data_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t procevent_cond = PTHREAD_COND_INITIALIZER;
+static int nl_sock = -1;
+static int buffer_length;
+static circbuf_t ring;
+static processlist_t *processlist_head = NULL;
+static int event_id = 0;
+
+static const char *config_keys[] = {"BufferLength", "Process", "ProcessRegex"};
+static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
+
+/*
+ * Private functions
+ */
+
+static int gen_message_payload(int state, long pid, char *process,
+                               cdtime_t timestamp, char **buf) {
+  const unsigned char *buf2;
+  yajl_gen g;
+  char json_str[DATA_MAX_NAME_LEN];
+
+#if !defined(HAVE_YAJL_V2)
+  yajl_gen_config conf = {0};
+#endif
+
+#if HAVE_YAJL_V2
+  size_t len;
+  g = yajl_gen_alloc(NULL);
+  yajl_gen_config(g, yajl_gen_beautify, 0);
+#else
+  unsigned int len;
+  g = yajl_gen_alloc(&conf, NULL);
+#endif
+
+  yajl_gen_clear(g);
+
+  // *** BEGIN common event header ***
+
+  if (yajl_gen_map_open(g) != yajl_gen_status_ok)
+    goto err;
+
+  // domain
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_DOMAIN_FIELD,
+                      strlen(PROCEVENT_DOMAIN_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_DOMAIN_VALUE,
+                      strlen(PROCEVENT_DOMAIN_VALUE)) != yajl_gen_status_ok)
+    goto err;
+
+  // eventId
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_EVENT_ID_FIELD,
+                      strlen(PROCEVENT_EVENT_ID_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  event_id = event_id + 1;
+  if (snprintf(json_str, sizeof(json_str), "%d", event_id) < 0) {
+    goto err;
+  }
+
+  if (yajl_gen_number(g, json_str, strlen(json_str)) != yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // eventName
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_EVENT_NAME_FIELD,
+                      strlen(PROCEVENT_EVENT_NAME_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (snprintf(json_str, sizeof(json_str), "process %s (%ld) %s", process, pid,
+               (state == 0 ? PROCEVENT_EVENT_NAME_DOWN_VALUE
+                           : PROCEVENT_EVENT_NAME_UP_VALUE)) < 0) {
+    goto err;
+  }
+
+  if (yajl_gen_string(g, (u_char *)json_str, strlen(json_str)) !=
+      yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // lastEpochMicrosec
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_LAST_EPOCH_MICROSEC_FIELD,
+                      strlen(PROCEVENT_LAST_EPOCH_MICROSEC_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (snprintf(json_str, sizeof(json_str), "%" PRIu64,
+               CDTIME_T_TO_US(cdtime())) < 0) {
+    goto err;
+  }
+
+  if (yajl_gen_number(g, json_str, strlen(json_str)) != yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // priority
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_PRIORITY_FIELD,
+                      strlen(PROCEVENT_PRIORITY_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_PRIORITY_VALUE,
+                      strlen(PROCEVENT_PRIORITY_VALUE)) != yajl_gen_status_ok)
+    goto err;
+
+  // reportingEntityName
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_REPORTING_ENTITY_NAME_FIELD,
+                      strlen(PROCEVENT_REPORTING_ENTITY_NAME_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_REPORTING_ENTITY_NAME_VALUE,
+                      strlen(PROCEVENT_REPORTING_ENTITY_NAME_VALUE)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // sequence
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_SEQUENCE_FIELD,
+                      strlen(PROCEVENT_SEQUENCE_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_number(g, PROCEVENT_SEQUENCE_VALUE,
+                      strlen(PROCEVENT_SEQUENCE_VALUE)) != yajl_gen_status_ok)
+    goto err;
+
+  // sourceName
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_SOURCE_NAME_FIELD,
+                      strlen(PROCEVENT_SOURCE_NAME_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)process, strlen(process)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // startEpochMicrosec
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_START_EPOCH_MICROSEC_FIELD,
+                      strlen(PROCEVENT_START_EPOCH_MICROSEC_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (snprintf(json_str, sizeof(json_str), "%" PRIu64,
+               CDTIME_T_TO_US(timestamp)) < 0) {
+    goto err;
+  }
+
+  if (yajl_gen_number(g, json_str, strlen(json_str)) != yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // version
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_VERSION_FIELD,
+                      strlen(PROCEVENT_VERSION_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_number(g, PROCEVENT_VERSION_VALUE,
+                      strlen(PROCEVENT_VERSION_VALUE)) != yajl_gen_status_ok)
+    goto err;
+
+  // *** END common event header ***
+
+  // *** BEGIN fault fields ***
+
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_FAULT_FIELDS_FIELD,
+                      strlen(PROCEVENT_FAULT_FIELDS_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_map_open(g) != yajl_gen_status_ok)
+    goto err;
+
+  // alarmCondition
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_ALARM_CONDITION_FIELD,
+                      strlen(PROCEVENT_ALARM_CONDITION_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (snprintf(json_str, sizeof(json_str), "process %s (%ld) state change",
+               process, pid) < 0) {
+    goto err;
+  }
+
+  if (yajl_gen_string(g, (u_char *)json_str, strlen(json_str)) !=
+      yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // alarmInterfaceA
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_ALARM_INTERFACE_A_FIELD,
+                      strlen(PROCEVENT_ALARM_INTERFACE_A_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)process, strlen(process)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // eventSeverity
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_EVENT_SEVERITY_FIELD,
+                      strlen(PROCEVENT_EVENT_SEVERITY_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(
+          g,
+          (u_char *)(state == 0 ? PROCEVENT_EVENT_SEVERITY_CRITICAL_VALUE
+                                : PROCEVENT_EVENT_SEVERITY_NORMAL_VALUE),
+          strlen((state == 0 ? PROCEVENT_EVENT_SEVERITY_CRITICAL_VALUE
+                             : PROCEVENT_EVENT_SEVERITY_NORMAL_VALUE))) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // eventSourceType
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_EVENT_SOURCE_TYPE_FIELD,
+                      strlen(PROCEVENT_EVENT_SOURCE_TYPE_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_EVENT_SOURCE_TYPE_VALUE,
+                      strlen(PROCEVENT_EVENT_SOURCE_TYPE_VALUE)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // faultFieldsVersion
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_FAULT_FIELDS_VERSION_FIELD,
+                      strlen(PROCEVENT_FAULT_FIELDS_VERSION_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_number(g, PROCEVENT_FAULT_FIELDS_VERSION_VALUE,
+                      strlen(PROCEVENT_FAULT_FIELDS_VERSION_VALUE)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // specificProblem
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_SPECIFIC_PROBLEM_FIELD,
+                      strlen(PROCEVENT_SPECIFIC_PROBLEM_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (snprintf(json_str, sizeof(json_str), "process %s (%ld) %s", process, pid,
+               (state == 0 ? PROCEVENT_SPECIFIC_PROBLEM_DOWN_VALUE
+                           : PROCEVENT_SPECIFIC_PROBLEM_UP_VALUE)) < 0) {
+    goto err;
+  }
+
+  if (yajl_gen_string(g, (u_char *)json_str, strlen(json_str)) !=
+      yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // vfStatus
+  if (yajl_gen_string(g, (u_char *)PROCEVENT_VF_STATUS_FIELD,
+                      strlen(PROCEVENT_VF_STATUS_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(
+          g,
+          (u_char *)(state == 0 ? PROCEVENT_VF_STATUS_CRITICAL_VALUE
+                                : PROCEVENT_VF_STATUS_NORMAL_VALUE),
+          strlen((state == 0 ? PROCEVENT_VF_STATUS_CRITICAL_VALUE
+                             : PROCEVENT_VF_STATUS_NORMAL_VALUE))) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // *** END fault fields ***
+
+  // close fault and header fields
+  if (yajl_gen_map_close(g) != yajl_gen_status_ok ||
+      yajl_gen_map_close(g) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_get_buf(g, &buf2, &len) != yajl_gen_status_ok)
+    goto err;
+
+  *buf = strdup((char *)buf2);
+
+  if (*buf == NULL) {
+    ERROR("procevent plugin: strdup failed during gen_message_payload: %s",
+          STRERRNO);
+    goto err;
+  }
+
+  yajl_gen_free(g);
+
+  return 0;
+
+err:
+  yajl_gen_free(g);
+  ERROR("procevent plugin: gen_message_payload failed to generate JSON");
+  return -1;
+}
+
+// Does /proc/<pid>/comm contain a process name we are interested in?
+// NOTE: Caller MUST hold procevent_data_lock when calling this function
+static processlist_t *process_check(long pid) {
+  char file[BUFSIZE];
+
+  int len = snprintf(file, sizeof(file), PROCDIR "/%ld/comm", pid);
+
+  if ((len < 0) || (len >= BUFSIZE)) {
+    WARNING("procevent process_check: process name too large");
+    return NULL;
+  }
+
+  FILE *fh;
+
+  if (NULL == (fh = fopen(file, "r"))) {
+    // No /proc/<pid>/comm for this pid, just ignore
+    DEBUG("procevent plugin: no comm file available for pid %ld", pid);
+    return NULL;
+  }
+
+  char buffer[BUFSIZE];
+  int retval = fscanf(fh, "%[^\n]", buffer);
+
+  if (retval < 0) {
+    WARNING("procevent process_check: unable to read comm file for pid %ld",
+            pid);
+    fclose(fh);
+    return NULL;
+  }
+
+  // Now that we have the process name in the buffer, check if we are
+  // even interested in it
+  if (ignorelist_match(ignorelist, buffer) != 0) {
+    DEBUG("procevent process_check: ignoring process %s (%ld)", buffer, pid);
+    fclose(fh);
+    return NULL;
+  }
+
+  if (fh != NULL) {
+    fclose(fh);
+    fh = NULL;
+  }
+
+  //
+  // Go through the processlist linked list and look for the process name
+  // in /proc/<pid>/comm.  If found:
+  // 1. If pl->pid is -1, then set pl->pid to <pid> (and return that object)
+  // 2. If pl->pid is not -1, then another <process name> process was already
+  //    found.  If <pid> == pl->pid, this is an old match, so do nothing.
+  //    If the <pid> is different, however, make a new processlist_t and
+  //    associate <pid> with it (with the same process name as the existing).
+  //
+
+  processlist_t *match = NULL;
+
+  for (processlist_t *pl = processlist_head; pl != NULL; pl = pl->next) {
+
+    int is_match = (strcmp(buffer, pl->process) == 0 ? 1 : 0);
+
+    if (is_match == 1) {
+      DEBUG("procevent plugin: process %ld name match for %s", pid, buffer);
+
+      if (pl->pid == pid) {
+        // this is a match, and we've already stored the exact pid/name combo
+        DEBUG("procevent plugin: found exact match with name %s, PID %ld for "
+              "incoming PID %ld",
+              pl->process, pl->pid, pid);
+        match = pl;
+        break;
+      } else if (pl->pid == -1) {
+        // this is a match, and we've found a candidate processlist_t to store
+        // this new pid/name combo
+        DEBUG("procevent plugin: reusing pl object with PID %ld for incoming "
+              "PID %ld",
+              pl->pid, pid);
+        pl->pid = pid;
+        match = pl;
+        break;
+      } else if (pl->pid != -1) {
+        // this is a match, but another instance of this process has already
+        // claimed this pid/name combo,
+        // so keep looking
+        DEBUG("procevent plugin: found pl object with matching name for "
+              "incoming PID %ld, but object is in use by PID %ld",
+              pid, pl->pid);
+        match = pl;
+        continue;
+      }
+    }
+  }
+
+  if (match == NULL ||
+      (match != NULL && match->pid != -1 && match->pid != pid)) {
+    // if there wasn't an existing match, OR
+    // if there was a match but the associated processlist_t object already
+    // contained a pid/name combo,
+    // then make a new one and add it to the linked list
+
+    DEBUG("procevent plugin: allocating new processlist_t object for PID %ld "
+          "(%s)",
+          pid, buffer);
+
+    processlist_t *pl2 = calloc(1, sizeof(*pl2));
+    if (pl2 == NULL) {
+      ERROR("procevent plugin: calloc failed during process_check: %s",
+            STRERRNO);
+      return NULL;
+    }
+
+    char *process = strdup(buffer);
+    if (process == NULL) {
+      sfree(pl2);
+      ERROR("procevent plugin: strdup failed during process_check: %s",
+            STRERRNO);
+      return NULL;
+    }
+
+    pl2->process = process;
+    pl2->pid = pid;
+    pl2->next = processlist_head;
+    processlist_head = pl2;
+
+    match = pl2;
+  }
+
+  return match;
+}
+
+// Does our map have this PID or name?
+// NOTE: Caller MUST hold procevent_data_lock when calling this function
+static processlist_t *process_map_check(long pid, char *process) {
+  for (processlist_t *pl = processlist_head; pl != NULL; pl = pl->next) {
+    int match_pid = 0;
+
+    if (pid > 0) {
+      if (pl->pid == pid)
+        match_pid = 1;
+    }
+
+    int match_process = 0;
+
+    if (process != NULL) {
+      if (strcmp(pl->process, process) == 0)
+        match_process = 1;
+    }
+
+    int match = 0;
+
+    if ((pid > 0 && process == NULL && match_pid == 1) ||
+        (pid < 0 && process != NULL && match_process == 1) ||
+        (pid > 0 && process != NULL && match_pid == 1 && match_process == 1)) {
+      match = 1;
+    }
+
+    if (match == 1) {
+      return pl;
+    }
+  }
+
+  return NULL;
+}
+
+static int process_map_refresh(void) {
+  errno = 0;
+  DIR *proc = opendir(PROCDIR);
+
+  if (proc == NULL) {
+    ERROR("procevent plugin: fopen (%s): %s", PROCDIR, STRERRNO);
+    return -1;
+  }
+
+  while (42) {
+    errno = 0;
+    struct dirent *dent = readdir(proc);
+    if (dent == NULL) {
+      if (errno == 0) /* end of directory */
+        break;
+
+      ERROR("procevent plugin: failed to read directory %s: %s", PROCDIR,
+            STRERRNO);
+      closedir(proc);
+      return -1;
+    }
+
+    if (dent->d_name[0] == '.')
+      continue;
+
+    char file[BUFSIZE];
+
+    int len = snprintf(file, sizeof(file), PROCDIR "/%s", dent->d_name);
+    if ((len < 0) || (len >= BUFSIZE))
+      continue;
+
+    struct stat statbuf;
+
+    int status = stat(file, &statbuf);
+    if (status != 0) {
+      WARNING("procevent plugin: stat (%s) failed: %s", file, STRERRNO);
+      continue;
+    }
+
+    if (!S_ISDIR(statbuf.st_mode))
+      continue;
+
+    len = snprintf(file, sizeof(file), PROCDIR "/%s/comm", dent->d_name);
+    if ((len < 0) || (len >= BUFSIZE))
+      continue;
+
+    int not_number = 0;
+
+    for (int i = 0; i < strlen(dent->d_name); i++) {
+      if (!isdigit(dent->d_name[i])) {
+        not_number = 1;
+        break;
+      }
+    }
+
+    if (not_number != 0)
+      continue;
+
+    // Check if we need to store this pid/name combo in our processlist_t linked
+    // list
+    int this_pid = atoi(dent->d_name);
+    pthread_mutex_lock(&procevent_data_lock);
+    processlist_t *pl = process_check(this_pid);
+    pthread_mutex_unlock(&procevent_data_lock);
+
+    if (pl != NULL)
+      DEBUG("procevent plugin: process map refreshed for PID %d and name %s",
+            this_pid, pl->process);
+  }
+
+  closedir(proc);
+
+  return 0;
+}
+
+static int nl_connect() {
+  struct sockaddr_nl sa_nl = {
+      .nl_family = AF_NETLINK,
+      .nl_groups = CN_IDX_PROC,
+      .nl_pid = getpid(),
+  };
+
+  nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+  if (nl_sock == -1) {
+    ERROR("procevent plugin: socket open failed: %d", errno);
+    return -1;
+  }
+
+  int rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
+  if (rc == -1) {
+    ERROR("procevent plugin: socket bind failed: %d", errno);
+    close(nl_sock);
+    nl_sock = -1;
+    return -1;
+  }
+
+  return 0;
+}
+
+static int set_proc_ev_listen(bool enable) {
+  struct __attribute__((aligned(NLMSG_ALIGNTO))) {
+    struct nlmsghdr nl_hdr;
+    struct __attribute__((__packed__)) {
+      struct cn_msg cn_msg;
+      enum proc_cn_mcast_op cn_mcast;
+    };
+  } nlcn_msg;
+
+  memset(&nlcn_msg, 0, sizeof(nlcn_msg));
+  nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg);
+  nlcn_msg.nl_hdr.nlmsg_pid = getpid();
+  nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE;
+
+  nlcn_msg.cn_msg.id.idx = CN_IDX_PROC;
+  nlcn_msg.cn_msg.id.val = CN_VAL_PROC;
+  nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op);
+
+  nlcn_msg.cn_mcast = enable ? PROC_CN_MCAST_LISTEN : PROC_CN_MCAST_IGNORE;
+
+  int rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
+  if (rc == -1) {
+    ERROR("procevent plugin: subscribing to netlink process events failed: %d",
+          errno);
+    return -1;
+  }
+
+  return 0;
+}
+
+// Read from netlink socket and write to ring buffer
+static int read_event() {
+  int recv_flags = MSG_DONTWAIT;
+  struct __attribute__((aligned(NLMSG_ALIGNTO))) {
+    struct nlmsghdr nl_hdr;
+    struct __attribute__((__packed__)) {
+      struct cn_msg cn_msg;
+      struct proc_event proc_ev;
+    };
+  } nlcn_msg;
+
+  if (nl_sock == -1)
+    return 0;
+
+  while (42) {
+    pthread_mutex_lock(&procevent_thread_lock);
+
+    if (procevent_netlink_thread_loop <= 0) {
+      pthread_mutex_unlock(&procevent_thread_lock);
+      return 0;
+    }
+
+    pthread_mutex_unlock(&procevent_thread_lock);
+
+    int status = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), recv_flags);
+
+    if (status == 0) {
+      return 0;
+    } else if (status < 0) {
+      if (errno == EAGAIN || errno == EWOULDBLOCK) {
+        pthread_mutex_lock(&procevent_data_lock);
+
+        // There was nothing more to receive for now, so...
+        // If ring head does not equal ring tail, then there is data
+        // in the ring buffer for the dequeue thread to read, so
+        // signal it
+        if (ring.head != ring.tail)
+          pthread_cond_signal(&procevent_cond);
+
+        pthread_mutex_unlock(&procevent_data_lock);
+
+        // Since there was nothing to receive, set recv to block and
+        // try again
+        recv_flags = 0;
+        continue;
+      } else if (errno != EINTR) {
+        ERROR("procevent plugin: socket receive error: %d", errno);
+        return -1;
+      } else {
+        // Interrupt, so just continue and try again
+        continue;
+      }
+    }
+
+    // We successfully received a message, so don't block on the next
+    // read in case there are more (and if there aren't, it will be
+    // handled above in the EWOULDBLOCK error-checking)
+    recv_flags = MSG_DONTWAIT;
+
+    int proc_id = -1;
+    int proc_status = -1;
+
+    switch (nlcn_msg.proc_ev.what) {
+    case PROC_EVENT_EXEC:
+      proc_status = PROCEVENT_STARTED;
+      proc_id = nlcn_msg.proc_ev.event_data.exec.process_pid;
+      break;
+    case PROC_EVENT_EXIT:
+      proc_id = nlcn_msg.proc_ev.event_data.exit.process_pid;
+      proc_status = PROCEVENT_EXITED;
+      break;
+    default:
+      // Otherwise not of interest
+      break;
+    }
+
+    // If we're interested in this process status event, place the event
+    // in the ring buffer for consumption by the dequeue (dispatch) thread.
+
+    if (proc_status != -1) {
+      pthread_mutex_lock(&procevent_data_lock);
+
+      int next = ring.head + 1;
+      if (next >= ring.maxLen)
+        next = 0;
+
+      if (next == ring.tail) {
+        // Buffer is full, signal the dequeue thread to process the buffer
+        // and clean it out, and then sleep
+        WARNING("procevent plugin: ring buffer full");
+
+        pthread_cond_signal(&procevent_cond);
+        pthread_mutex_unlock(&procevent_data_lock);
+
+        usleep(1000);
+        continue;
+      } else {
+        DEBUG("procevent plugin: Process %d status is now %s at %llu", proc_id,
+              (proc_status == PROCEVENT_EXITED ? "EXITED" : "STARTED"),
+              (unsigned long long)cdtime());
+
+        ring.buffer[ring.head][RBUF_PROC_ID_INDEX] = proc_id;
+        ring.buffer[ring.head][RBUF_PROC_STATUS_INDEX] = proc_status;
+        ring.buffer[ring.head][RBUF_TIME_INDEX] = cdtime();
+
+        ring.head = next;
+      }
+
+      pthread_mutex_unlock(&procevent_data_lock);
+    }
+  }
+
+  return 0;
+}
+
+static void procevent_dispatch_notification(long pid, gauge_t value,
+                                            char *process, cdtime_t timestamp) {
+
+  notification_t n = {
+      .severity = (value == 1 ? NOTIF_OKAY : NOTIF_FAILURE),
+      .time = cdtime(),
+      .plugin = "procevent",
+      .type = "gauge",
+      .type_instance = "process_status",
+  };
+
+  sstrncpy(n.host, hostname_g, sizeof(n.host));
+  sstrncpy(n.plugin_instance, process, sizeof(n.plugin_instance));
+
+  char *buf = NULL;
+  gen_message_payload(value, pid, process, timestamp, &buf);
+
+  int status = plugin_notification_meta_add_string(&n, "ves", buf);
+
+  if (status < 0) {
+    sfree(buf);
+    ERROR("procevent plugin: unable to set notification VES metadata: %s",
+          STRERRNO);
+    return;
+  }
+
+  DEBUG("procevent plugin: notification VES metadata: %s",
+        n.meta->nm_value.nm_string);
+
+  DEBUG("procevent plugin: dispatching state %d for PID %ld (%s)", (int)value,
+        pid, process);
+
+  plugin_dispatch_notification(&n);
+  plugin_notification_meta_free(n.meta);
+
+  // strdup'd in gen_message_payload
+  if (buf != NULL)
+    sfree(buf);
+}
+
+// Read from ring buffer and dispatch to write plugins
+static void read_ring_buffer() {
+  pthread_mutex_lock(&procevent_data_lock);
+
+  // If there's currently nothing to read from the buffer,
+  // then wait
+  if (ring.head == ring.tail)
+    pthread_cond_wait(&procevent_cond, &procevent_data_lock);
+
+  while (ring.head != ring.tail) {
+    int next = ring.tail + 1;
+
+    if (next >= ring.maxLen)
+      next = 0;
+
+    if (ring.buffer[ring.tail][RBUF_PROC_STATUS_INDEX] == PROCEVENT_EXITED) {
+      processlist_t *pl = process_map_check(ring.buffer[ring.tail][0], NULL);
+
+      if (pl != NULL) {
+        // This process is of interest to us, so publish its EXITED status
+        procevent_dispatch_notification(
+            ring.buffer[ring.tail][RBUF_PROC_ID_INDEX],
+            ring.buffer[ring.tail][RBUF_PROC_STATUS_INDEX], pl->process,
+            ring.buffer[ring.tail][RBUF_TIME_INDEX]);
+        DEBUG(
+            "procevent plugin: PID %ld (%s) EXITED, removing PID from process "
+            "list",
+            pl->pid, pl->process);
+        pl->pid = -1;
+        pl->last_status = -1;
+      }
+    } else if (ring.buffer[ring.tail][RBUF_PROC_STATUS_INDEX] ==
+               PROCEVENT_STARTED) {
+      // a new process has started, so check if we should monitor it
+      processlist_t *pl = process_check(ring.buffer[ring.tail][0]);
+
+      // If we had already seen this process name and pid combo before,
+      // and the last message was a "process started" message, don't send
+      // the notfication again
+
+      if (pl != NULL && pl->last_status != PROCEVENT_STARTED) {
+        // This process is of interest to us, so publish its STARTED status
+        procevent_dispatch_notification(
+            ring.buffer[ring.tail][RBUF_PROC_ID_INDEX],
+            ring.buffer[ring.tail][RBUF_PROC_STATUS_INDEX], pl->process,
+            ring.buffer[ring.tail][RBUF_TIME_INDEX]);
+
+        pl->last_status = PROCEVENT_STARTED;
+
+        DEBUG("procevent plugin: PID %ld (%s) STARTED, adding PID to process "
+              "list",
+              pl->pid, pl->process);
+      }
+    }
+
+    ring.tail = next;
+  }
+
+  pthread_mutex_unlock(&procevent_data_lock);
+}
+
+// Entry point for thread responsible for listening
+// to netlink socket and writing data to ring buffer
+static void *procevent_netlink_thread(void *arg) /* {{{ */
+{
+  pthread_mutex_lock(&procevent_thread_lock);
+
+  while (procevent_netlink_thread_loop > 0) {
+    pthread_mutex_unlock(&procevent_thread_lock);
+
+    int status = read_event();
+
+    pthread_mutex_lock(&procevent_thread_lock);
+
+    if (status < 0) {
+      procevent_netlink_thread_error = 1;
+      break;
+    }
+  } /* while (procevent_netlink_thread_loop > 0) */
+
+  pthread_mutex_unlock(&procevent_thread_lock);
+
+  return (void *)0;
+} /* }}} void *procevent_netlink_thread */
+
+// Entry point for thread responsible for reading from
+// ring buffer and dispatching notifications
+static void *procevent_dequeue_thread(void *arg) /* {{{ */
+{
+  pthread_mutex_lock(&procevent_thread_lock);
+
+  while (procevent_dequeue_thread_loop > 0) {
+    pthread_mutex_unlock(&procevent_thread_lock);
+
+    read_ring_buffer();
+
+    pthread_mutex_lock(&procevent_thread_lock);
+  } /* while (procevent_dequeue_thread_loop > 0) */
+
+  pthread_mutex_unlock(&procevent_thread_lock);
+
+  return (void *)0;
+} /* }}} void *procevent_dequeue_thread */
+
+static int start_netlink_thread(void) /* {{{ */
+{
+  pthread_mutex_lock(&procevent_thread_lock);
+
+  if (procevent_netlink_thread_loop != 0) {
+    pthread_mutex_unlock(&procevent_thread_lock);
+    return 0;
+  }
+
+  int status;
+
+  if (nl_sock == -1) {
+    status = nl_connect();
+
+    if (status != 0) {
+      pthread_mutex_unlock(&procevent_thread_lock);
+      return status;
+    }
+
+    status = set_proc_ev_listen(true);
+    if (status == -1) {
+      pthread_mutex_unlock(&procevent_thread_lock);
+      return status;
+    }
+  }
+
+  DEBUG("procevent plugin: socket created and bound");
+
+  procevent_netlink_thread_loop = 1;
+  procevent_netlink_thread_error = 0;
+
+  status = plugin_thread_create(&procevent_netlink_thread_id, /* attr = */ NULL,
+                                procevent_netlink_thread,
+                                /* arg = */ (void *)0, "procevent");
+  if (status != 0) {
+    procevent_netlink_thread_loop = 0;
+    ERROR("procevent plugin: Starting netlink thread failed.");
+    pthread_mutex_unlock(&procevent_thread_lock);
+
+    int status2 = close(nl_sock);
+
+    if (status2 != 0) {
+      ERROR("procevent plugin: failed to close socket %d: %d (%s)", nl_sock,
+            status2, STRERRNO);
+    }
+
+    nl_sock = -1;
+
+    return -1;
+  }
+
+  pthread_mutex_unlock(&procevent_thread_lock);
+
+  return status;
+} /* }}} int start_netlink_thread */
+
+static int start_dequeue_thread(void) /* {{{ */
+{
+  pthread_mutex_lock(&procevent_thread_lock);
+
+  if (procevent_dequeue_thread_loop != 0) {
+    pthread_mutex_unlock(&procevent_thread_lock);
+    return 0;
+  }
+
+  procevent_dequeue_thread_loop = 1;
+
+  int status = plugin_thread_create(&procevent_dequeue_thread_id,
+                                    /* attr = */ NULL, procevent_dequeue_thread,
+                                    /* arg = */ (void *)0, "procevent");
+  if (status != 0) {
+    procevent_dequeue_thread_loop = 0;
+    ERROR("procevent plugin: Starting dequeue thread failed.");
+    pthread_mutex_unlock(&procevent_thread_lock);
+    return -1;
+  }
+
+  pthread_mutex_unlock(&procevent_thread_lock);
+
+  return status;
+} /* }}} int start_dequeue_thread */
+
+static int start_threads(void) /* {{{ */
+{
+  int status = start_netlink_thread();
+  int status2 = start_dequeue_thread();
+
+  if (status != 0)
+    return status;
+  else
+    return status2;
+} /* }}} int start_threads */
+
+static int stop_netlink_thread(int shutdown) /* {{{ */
+{
+  int socket_status;
+
+  if (nl_sock != -1) {
+    socket_status = close(nl_sock);
+    if (socket_status != 0) {
+      ERROR("procevent plugin: failed to close socket %d: %d (%s)", nl_sock,
+            socket_status, strerror(errno));
+    }
+
+    nl_sock = -1;
+  } else
+    socket_status = 0;
+
+  pthread_mutex_lock(&procevent_thread_lock);
+
+  if (procevent_netlink_thread_loop == 0) {
+    pthread_mutex_unlock(&procevent_thread_lock);
+    return -1;
+  }
+
+  // Set thread termination status
+  procevent_netlink_thread_loop = 0;
+  pthread_mutex_unlock(&procevent_thread_lock);
+
+  // Let threads waiting on access to the data know to move
+  // on such that they'll see the thread's termination status
+  pthread_cond_broadcast(&procevent_cond);
+
+  int thread_status;
+
+  if (shutdown == 1) {
+    // Calling pthread_cancel here in
+    // the case of a shutdown just assures that the thread is
+    // gone and that the process has been fully terminated.
+
+    DEBUG("procevent plugin: Canceling netlink thread for process shutdown");
+
+    thread_status = pthread_cancel(procevent_netlink_thread_id);
+
+    if (thread_status != 0 && thread_status != ESRCH) {
+      ERROR("procevent plugin: Unable to cancel netlink thread: %d",
+            thread_status);
+      thread_status = -1;
+    } else
+      thread_status = 0;
+  } else {
+    thread_status =
+        pthread_join(procevent_netlink_thread_id, /* return = */ NULL);
+    if (thread_status != 0 && thread_status != ESRCH) {
+      ERROR("procevent plugin: Stopping netlink thread failed.");
+      thread_status = -1;
+    } else
+      thread_status = 0;
+  }
+
+  pthread_mutex_lock(&procevent_thread_lock);
+  memset(&procevent_netlink_thread_id, 0, sizeof(procevent_netlink_thread_id));
+  procevent_netlink_thread_error = 0;
+  pthread_mutex_unlock(&procevent_thread_lock);
+
+  DEBUG("procevent plugin: Finished requesting stop of netlink thread");
+
+  if (socket_status != 0)
+    return socket_status;
+  else
+    return thread_status;
+} /* }}} int stop_netlink_thread */
+
+static int stop_dequeue_thread() /* {{{ */
+{
+  pthread_mutex_lock(&procevent_thread_lock);
+
+  if (procevent_dequeue_thread_loop == 0) {
+    pthread_mutex_unlock(&procevent_thread_lock);
+    return -1;
+  }
+
+  procevent_dequeue_thread_loop = 0;
+  pthread_mutex_unlock(&procevent_thread_lock);
+
+  pthread_cond_broadcast(&procevent_cond);
+
+  // Calling pthread_cancel here just assures that the thread is
+  // gone and that the process has been fully terminated.
+
+  DEBUG("procevent plugin: Canceling dequeue thread for process shutdown");
+
+  int status = pthread_cancel(procevent_dequeue_thread_id);
+
+  if (status != 0 && status != ESRCH) {
+    ERROR("procevent plugin: Unable to cancel dequeue thread: %d", status);
+    status = -1;
+  } else
+    status = 0;
+
+  pthread_mutex_lock(&procevent_thread_lock);
+  memset(&procevent_dequeue_thread_id, 0, sizeof(procevent_dequeue_thread_id));
+  pthread_mutex_unlock(&procevent_thread_lock);
+
+  DEBUG("procevent plugin: Finished requesting stop of dequeue thread");
+
+  return status;
+} /* }}} int stop_dequeue_thread */
+
+static int stop_threads() /* {{{ */
+{
+  int status = stop_netlink_thread(1);
+  int status2 = stop_dequeue_thread();
+
+  if (status != 0)
+    return status;
+  else
+    return status2;
+} /* }}} int stop_threads */
+
+static int procevent_init(void) /* {{{ */
+{
+  ring.head = 0;
+  ring.tail = 0;
+  ring.maxLen = buffer_length;
+  ring.buffer = (cdtime_t **)calloc(buffer_length, sizeof(cdtime_t *));
+
+  for (int i = 0; i < buffer_length; i++) {
+    ring.buffer[i] = (cdtime_t *)calloc(PROCEVENT_FIELDS, sizeof(cdtime_t));
+  }
+
+  int status = process_map_refresh();
+
+  if (status == -1) {
+    ERROR("procevent plugin: Initial process mapping failed.");
+    return -1;
+  }
+
+  if (ignorelist == NULL) {
+    NOTICE("procevent plugin: No processes have been configured.");
+    return -1;
+  }
+
+  return start_threads();
+} /* }}} int procevent_init */
+
+static int procevent_config(const char *key, const char *value) /* {{{ */
+{
+  if (ignorelist == NULL)
+    ignorelist = ignorelist_create(/* invert = */ 1);
+
+  if (ignorelist == NULL) {
+    return -1;
+  }
+
+  if (strcasecmp(key, "BufferLength") == 0) {
+    buffer_length = atoi(value);
+  } else if (strcasecmp(key, "Process") == 0) {
+    ignorelist_add(ignorelist, value);
+  } else if (strcasecmp(key, "ProcessRegex") == 0) {
+#if HAVE_REGEX_H
+    int status = ignorelist_add(ignorelist, value);
+
+    if (status != 0) {
+      ERROR("procevent plugin: invalid regular expression: %s", value);
+      return 1;
+    }
+#else
+    WARNING("procevent plugin: The plugin has been compiled without support "
+            "for the \"ProcessRegex\" option.");
+#endif
+  } else {
+    return -1;
+  }
+
+  return 0;
+} /* }}} int procevent_config */
+
+static int procevent_read(void) /* {{{ */
+{
+  pthread_mutex_lock(&procevent_thread_lock);
+
+  if (procevent_netlink_thread_error != 0) {
+
+    pthread_mutex_unlock(&procevent_thread_lock);
+
+    ERROR("procevent plugin: The netlink thread had a problem. Restarting it.");
+
+    stop_netlink_thread(0);
+
+    start_netlink_thread();
+
+    return -1;
+  } /* if (procevent_netlink_thread_error != 0) */
+
+  pthread_mutex_unlock(&procevent_thread_lock);
+
+  return 0;
+} /* }}} int procevent_read */
+
+static int procevent_shutdown(void) /* {{{ */
+{
+  DEBUG("procevent plugin: Shutting down threads.");
+
+  int status = stop_threads();
+
+  for (int i = 0; i < buffer_length; i++) {
+    free(ring.buffer[i]);
+  }
+
+  free(ring.buffer);
+
+  processlist_t *pl = processlist_head;
+  while (pl != NULL) {
+    processlist_t *pl_next;
+
+    pl_next = pl->next;
+
+    sfree(pl->process);
+    sfree(pl);
+
+    pl = pl_next;
+  }
+
+  ignorelist_free(ignorelist);
+
+  return status;
+} /* }}} int procevent_shutdown */
+
+void module_register(void) {
+  plugin_register_config("procevent", procevent_config, config_keys,
+                         config_keys_num);
+  plugin_register_init("procevent", procevent_init);
+  plugin_register_read("procevent", procevent_read);
+  plugin_register_shutdown("procevent", procevent_shutdown);
+} /* void module_register */
index 65b450c..7bfa663 100644 (file)
@@ -41,7 +41,8 @@
  * Global variables
  */
 static const char *config_keys[] = {
-    "Value", "IgnoreSelected",
+    "Value",
+    "IgnoreSelected",
 };
 static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
 
@@ -154,8 +155,8 @@ static int read_file(const char *path) {
       if (values_list != NULL) {
         char match_name[2 * DATA_MAX_NAME_LEN];
 
-        snprintf(match_name, sizeof(match_name), "%s:%s", key_buffer,
-                 key_fields[i]);
+        ssnprintf(match_name, sizeof(match_name), "%s:%s", key_buffer,
+                  key_fields[i]);
 
         if (ignorelist_match(values_list, match_name))
           continue;
index 9d47d70..70db6b6 100644 (file)
@@ -285,7 +285,7 @@ static void cpy_build_name(char *buf, size_t size, PyObject *callback,
   PyObject *mod = NULL;
 
   if (name != NULL) {
-    snprintf(buf, size, "python.%s", name);
+    ssnprintf(buf, size, "python.%s", name);
     return;
   }
 
@@ -294,14 +294,14 @@ static void cpy_build_name(char *buf, size_t size, PyObject *callback,
     module = cpy_unicode_or_bytes_to_string(&mod);
 
   if (module != NULL) {
-    snprintf(buf, size, "python.%s", module);
+    ssnprintf(buf, size, "python.%s", module);
     Py_XDECREF(mod);
     PyErr_Clear();
     return;
   }
   Py_XDECREF(mod);
 
-  snprintf(buf, size, "python.%p", callback);
+  ssnprintf(buf, size, "python.%p", callback);
   PyErr_Clear();
 }
 
@@ -703,8 +703,9 @@ static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
   for (size_t i = 0; i < ds->ds_num; ++i) {
     tuple = PyTuple_New(4);
     PyTuple_SET_ITEM(tuple, 0, cpy_string_to_unicode_or_bytes(ds->ds[i].name));
-    PyTuple_SET_ITEM(tuple, 1, cpy_string_to_unicode_or_bytes(
-                                   DS_TYPE_TO_STRING(ds->ds[i].type)));
+    PyTuple_SET_ITEM(
+        tuple, 1,
+        cpy_string_to_unicode_or_bytes(DS_TYPE_TO_STRING(ds->ds[i].type)));
     PyTuple_SET_ITEM(tuple, 2, float_or_none(ds->ds[i].min));
     PyTuple_SET_ITEM(tuple, 3, float_or_none(ds->ds[i].max));
     PyList_SET_ITEM(list, i, tuple);
@@ -774,7 +775,8 @@ static PyObject *cpy_register_generic_userdata(void *reg, void *handler,
 
   register_function(buf, handler,
                     &(user_data_t){
-                        .data = c, .free_func = cpy_destroy_user_data,
+                        .data = c,
+                        .free_func = cpy_destroy_user_data,
                     });
 
   ++cpy_num_callbacks;
@@ -817,7 +819,8 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args,
       /* group = */ "python", buf, cpy_read_callback,
       DOUBLE_TO_CDTIME_T(interval),
       &(user_data_t){
-          .data = c, .free_func = cpy_destroy_user_data,
+          .data = c,
+          .free_func = cpy_destroy_user_data,
       });
   ++cpy_num_callbacks;
   return cpy_string_to_unicode_or_bytes(buf);
@@ -1201,8 +1204,9 @@ static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
   values = PyTuple_New(ci->values_num); /* New reference. */
   for (int i = 0; i < ci->values_num; ++i) {
     if (ci->values[i].type == OCONFIG_TYPE_STRING) {
-      PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(
-                                      ci->values[i].value.string));
+      PyTuple_SET_ITEM(
+          values, i,
+          cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
     } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
       PyTuple_SET_ITEM(values, i,
                        PyFloat_FromDouble(ci->values[i].value.number));
index 37dc8d6..77ce5fb 100644 (file)
@@ -115,7 +115,7 @@ static int redis_node_add(redis_node_t *rn) /* {{{ */
   redis_have_instances = true;
 
   char cb_name[sizeof("redis/") + DATA_MAX_NAME_LEN];
-  snprintf(cb_name, sizeof(cb_name), "redis/%s", rn->name);
+  ssnprintf(cb_name, sizeof(cb_name), "redis/%s", rn->name);
 
   return plugin_register_complex_read(
       /* group = */ "redis",
@@ -123,7 +123,8 @@ static int redis_node_add(redis_node_t *rn) /* {{{ */
       /* callback  = */ redis_read,
       /* interval  = */ 0,
       &(user_data_t){
-          .data = rn, .free_func = redis_node_free,
+          .data = rn,
+          .free_func = redis_node_free,
       });
 } /* }}} */
 
@@ -486,7 +487,7 @@ static int redis_db_stats(const char *node, char const *info_line) /* {{{ */
     char *str;
     int i;
 
-    snprintf(field_name, sizeof(field_name), "db%d:keys=", db);
+    ssnprintf(field_name, sizeof(field_name), "db%d:keys=", db);
 
     str = strstr(info_line, field_name);
     if (!str)
@@ -502,7 +503,7 @@ static int redis_db_stats(const char *node, char const *info_line) /* {{{ */
       return -1;
     }
 
-    snprintf(db_id, sizeof(db_id), "%d", db);
+    ssnprintf(db_id, sizeof(db_id), "%d", db);
     redis_submit(node, "records", db_id, val);
   }
   return 0;
index 70dd75e..ece865b 100644 (file)
@@ -53,7 +53,8 @@ static void cr_submit_io(cr_data_t *rd, const char *type, /* {{{ */
                          const char *type_instance, derive_t rx, derive_t tx) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = rx}, {.derive = tx},
+      {.derive = rx},
+      {.derive = tx},
   };
 
   vl.values = values;
@@ -150,8 +151,8 @@ static void submit_regtable(cr_data_t *rd, /* {{{ */
     name = "default";
 
   /*** RX ***/
-  snprintf(type_instance, sizeof(type_instance), "%s-%s-rx", r->interface,
-           name);
+  ssnprintf(type_instance, sizeof(type_instance), "%s-%s-rx", r->interface,
+            name);
   cr_submit_gauge(rd, "bitrate", type_instance,
                   (gauge_t)(1000000.0 * r->rx_rate));
   cr_submit_gauge(rd, "signal_power", type_instance,
@@ -159,8 +160,8 @@ static void submit_regtable(cr_data_t *rd, /* {{{ */
   cr_submit_gauge(rd, "signal_quality", type_instance, (gauge_t)r->rx_ccq);
 
   /*** TX ***/
-  snprintf(type_instance, sizeof(type_instance), "%s-%s-tx", r->interface,
-           name);
+  ssnprintf(type_instance, sizeof(type_instance), "%s-%s-tx", r->interface,
+            name);
   cr_submit_gauge(rd, "bitrate", type_instance,
                   (gauge_t)(1000000.0 * r->tx_rate));
   cr_submit_gauge(rd, "signal_power", type_instance,
@@ -168,7 +169,7 @@ static void submit_regtable(cr_data_t *rd, /* {{{ */
   cr_submit_gauge(rd, "signal_quality", type_instance, (gauge_t)r->tx_ccq);
 
   /*** RX / TX ***/
-  snprintf(type_instance, sizeof(type_instance), "%s-%s", r->interface, name);
+  ssnprintf(type_instance, sizeof(type_instance), "%s-%s", r->interface, name);
   cr_submit_io(rd, "if_octets", type_instance, (derive_t)r->rx_bytes,
                (derive_t)r->tx_bytes);
   cr_submit_gauge(rd, "snr", type_instance, (gauge_t)r->signal_to_noise);
@@ -438,11 +439,12 @@ static int cr_config_router(oconfig_item_t *ci) /* {{{ */
     return status;
   }
 
-  snprintf(read_name, sizeof(read_name), "routeros/%s", router_data->node);
+  ssnprintf(read_name, sizeof(read_name), "routeros/%s", router_data->node);
   return plugin_register_complex_read(
       /* group = */ NULL, read_name, cr_read, /* interval = */ 0,
       &(user_data_t){
-          .data = router_data, .free_func = (void *)cr_free_data,
+          .data = router_data,
+          .free_func = (void *)cr_free_data,
       });
 } /* }}} int cr_config_router */
 
index 9aeb71a..1e75ff8 100644 (file)
@@ -67,7 +67,7 @@ static int value_list_to_string(char *buffer, int buffer_len,
   memset(buffer, '\0', buffer_len);
 
   int status =
-      snprintf(buffer, buffer_len, "%.6f", CDTIME_T_TO_DOUBLE(vl->time));
+      ssnprintf(buffer, buffer_len, "%.6f", CDTIME_T_TO_DOUBLE(vl->time));
   if ((status < 1) || (status >= buffer_len))
     return -1;
   int offset = status;
@@ -80,17 +80,17 @@ static int value_list_to_string(char *buffer, int buffer_len,
       return -1;
 
     if (ds->ds[i].type == DS_TYPE_COUNTER) {
-      status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
-                        (uint64_t)vl->values[i].counter);
+      status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
+                         (uint64_t)vl->values[i].counter);
     } else if (ds->ds[i].type == DS_TYPE_GAUGE) {
-      status = snprintf(buffer + offset, buffer_len - offset, ":%f",
-                        vl->values[i].gauge);
+      status = ssnprintf(buffer + offset, buffer_len - offset, ":%f",
+                         vl->values[i].gauge);
     } else if (ds->ds[i].type == DS_TYPE_DERIVE) {
-      status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIi64,
-                        vl->values[i].derive);
+      status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIi64,
+                         vl->values[i].derive);
     } else /* if (ds->ds[i].type == DS_TYPE_ABSOLUTE) */ {
-      status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
-                        vl->values[i].absolute);
+      status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
+                         vl->values[i].absolute);
     }
 
     if ((status < 1) || (status >= (buffer_len - offset)))
@@ -426,7 +426,8 @@ static int rc_write(const data_set_t *ds, const value_list_t *vl,
   }
 
   char *values_array[2] = {
-          [0] = values, [1] = NULL,
+      [0] = values,
+      [1] = NULL,
   };
 
   while (42) {
@@ -461,9 +462,9 @@ static int rc_flush(__attribute__((unused)) cdtime_t timeout, /* {{{ */
   char filename[PATH_MAX + 1];
 
   if (datadir != NULL)
-    snprintf(filename, sizeof(filename), "%s/%s.rrd", datadir, identifier);
+    ssnprintf(filename, sizeof(filename), "%s/%s.rrd", datadir, identifier);
   else
-    snprintf(filename, sizeof(filename), "%s.rrd", identifier);
+    ssnprintf(filename, sizeof(filename), "%s.rrd", identifier);
 
   rrd_clear_error();
   int status = rrdc_connect(daemon_address);
index d0849d1..bd5943c 100644 (file)
@@ -120,7 +120,7 @@ static int srrd_update(char *filename, char *template, int argc,
 
   return status;
 } /* int srrd_update */
-/* #endif HAVE_THREADSAFE_LIBRRD */
+  /* #endif HAVE_THREADSAFE_LIBRRD */
 
 #else  /* !HAVE_THREADSAFE_LIBRRD */
 static int srrd_update(char *filename, char *template, int argc,
@@ -173,7 +173,7 @@ static int value_list_to_string_multiple(char *buffer, int buffer_len,
   memset(buffer, '\0', buffer_len);
 
   tt = CDTIME_T_TO_TIME_T(vl->time);
-  status = snprintf(buffer, buffer_len, "%u", (unsigned int)tt);
+  status = ssnprintf(buffer, buffer_len, "%u", (unsigned int)tt);
   if ((status < 1) || (status >= buffer_len))
     return -1;
   offset = status;
@@ -186,17 +186,17 @@ static int value_list_to_string_multiple(char *buffer, int buffer_len,
       return -1;
 
     if (ds->ds[i].type == DS_TYPE_COUNTER)
-      status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
-                        (uint64_t)vl->values[i].counter);
+      status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
+                         (uint64_t)vl->values[i].counter);
     else if (ds->ds[i].type == DS_TYPE_GAUGE)
-      status = snprintf(buffer + offset, buffer_len - offset, ":" GAUGE_FORMAT,
-                        vl->values[i].gauge);
+      status = ssnprintf(buffer + offset, buffer_len - offset, ":" GAUGE_FORMAT,
+                         vl->values[i].gauge);
     else if (ds->ds[i].type == DS_TYPE_DERIVE)
-      status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIi64,
-                        vl->values[i].derive);
+      status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIi64,
+                         vl->values[i].derive);
     else /*if (ds->ds[i].type == DS_TYPE_ABSOLUTE) */
-      status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
-                        vl->values[i].absolute);
+      status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
+                         vl->values[i].absolute);
 
     if ((status < 1) || (status >= (buffer_len - offset)))
       return -1;
@@ -218,20 +218,20 @@ static int value_list_to_string(char *buffer, int buffer_len,
   tt = CDTIME_T_TO_TIME_T(vl->time);
   switch (ds->ds[0].type) {
   case DS_TYPE_DERIVE:
-    status = snprintf(buffer, buffer_len, "%u:%" PRIi64, (unsigned)tt,
-                      vl->values[0].derive);
+    status = ssnprintf(buffer, buffer_len, "%u:%" PRIi64, (unsigned)tt,
+                       vl->values[0].derive);
     break;
   case DS_TYPE_GAUGE:
-    status = snprintf(buffer, buffer_len, "%u:" GAUGE_FORMAT, (unsigned)tt,
-                      vl->values[0].gauge);
+    status = ssnprintf(buffer, buffer_len, "%u:" GAUGE_FORMAT, (unsigned)tt,
+                       vl->values[0].gauge);
     break;
   case DS_TYPE_COUNTER:
-    status = snprintf(buffer, buffer_len, "%u:%" PRIu64, (unsigned)tt,
-                      (uint64_t)vl->values[0].counter);
+    status = ssnprintf(buffer, buffer_len, "%u:%" PRIu64, (unsigned)tt,
+                       (uint64_t)vl->values[0].counter);
     break;
   case DS_TYPE_ABSOLUTE:
-    status = snprintf(buffer, buffer_len, "%u:%" PRIu64, (unsigned)tt,
-                      vl->values[0].absolute);
+    status = ssnprintf(buffer, buffer_len, "%u:%" PRIu64, (unsigned)tt,
+                       vl->values[0].absolute);
     break;
   default:
     return EINVAL;
@@ -566,9 +566,9 @@ static int rrd_cache_flush_identifier(cdtime_t timeout,
   now = cdtime();
 
   if (datadir == NULL)
-    snprintf(key, sizeof(key), "%s.rrd", identifier);
+    ssnprintf(key, sizeof(key), "%s.rrd", identifier);
   else
-    snprintf(key, sizeof(key), "%s/%s.rrd", datadir, identifier);
+    ssnprintf(key, sizeof(key), "%s/%s.rrd", datadir, identifier);
   key[sizeof(key) - 1] = '\0';
 
   status = c_avl_get(cache, key, (void *)&rc);
index 8d1ece9..61868e8 100644 (file)
@@ -230,7 +230,7 @@ static int sensors_load_conf(void) {
       last_feature = fl;
     } /* while sensors_get_all_features */
   }   /* while sensors_get_detected_chips */
-/* #endif SENSORS_API_VERSION < 0x400 */
+      /* #endif SENSORS_API_VERSION < 0x400 */
 
 #elif (SENSORS_API_VERSION >= 0x400)
   chip_num = 0;
@@ -368,7 +368,7 @@ static int sensors_read(void) {
     sensors_submit(plugin_instance, sensor_type_name_map[fl->type],
                    type_instance, value);
   } /* for fl = first_feature .. NULL */
-/* #endif SENSORS_API_VERSION < 0x400 */
+    /* #endif SENSORS_API_VERSION < 0x400 */
 
 #elif (SENSORS_API_VERSION >= 0x400)
   for (featurelist_t *fl = first_feature; fl != NULL; fl = fl->next) {
index aae9978..ae6f443 100644 (file)
@@ -33,7 +33,8 @@
 static void serial_submit(const char *type_instance, derive_t rx, derive_t tx) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = rx}, {.derive = tx},
+      {.derive = rx},
+      {.derive = tx},
   };
 
   vl.values = values;
index a8b67af..07bd1c8 100644 (file)
@@ -247,10 +247,10 @@ static int sigrok_init_driver(struct config_device *cfdev,
   }
   cfdev->sdi = devlist->data;
   g_slist_free(devlist);
-  snprintf(hwident, sizeof(hwident), "%s %s %s",
-           cfdev->sdi->vendor ? cfdev->sdi->vendor : "",
-           cfdev->sdi->model ? cfdev->sdi->model : "",
-           cfdev->sdi->version ? cfdev->sdi->version : "");
+  ssnprintf(hwident, sizeof(hwident), "%s %s %s",
+            cfdev->sdi->vendor ? cfdev->sdi->vendor : "",
+            cfdev->sdi->model ? cfdev->sdi->model : "",
+            cfdev->sdi->version ? cfdev->sdi->version : "");
   INFO("sigrok plugin: Device \"%s\" is a %s", cfdev->name, hwident);
 
   if (sr_dev_open(cfdev->sdi) != SR_OK)
index 2dfb924..627c16d 100644 (file)
@@ -116,9 +116,9 @@ static void handle_attribute(SkDisk *d, const SkSmartAttributeParsedData *a,
     sstrncpy(notif.host, hostname_g, sizeof(notif.host));
     sstrncpy(notif.plugin_instance, name, sizeof(notif.plugin_instance));
     sstrncpy(notif.type_instance, a->name, sizeof(notif.type_instance));
-    snprintf(notif.message, sizeof(notif.message),
-             "attribute %s is below allowed threshold (%d < %d)", a->name,
-             a->current_value, a->threshold);
+    ssnprintf(notif.message, sizeof(notif.message),
+              "attribute %s is below allowed threshold (%d < %d)", a->name,
+              a->current_value, a->threshold);
     plugin_dispatch_notification(&notif);
   }
 }
index c921e02..98da2b8 100644 (file)
@@ -99,6 +99,7 @@ struct host_definition_s {
   c_complain_t complaint;
   data_definition_t **data_list;
   int data_list_len;
+  int bulk_size;
 };
 typedef struct host_definition_s host_definition_t;
 
@@ -171,7 +172,7 @@ static int csnmp_oid_to_string(char *buffer, size_t buffer_size,
   char *oid_str_ptr[MAX_OID_LEN];
 
   for (size_t i = 0; i < o->oid_len; i++) {
-    snprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
+    ssnprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
     oid_str_ptr[i] = oid_str[i];
   }
 
@@ -762,6 +763,7 @@ static int csnmp_config_add_host(oconfig_item_t *ci) {
   /* These mean that we have not set a timeout or retry value */
   hd->timeout = 0;
   hd->retries = -1;
+  hd->bulk_size = 0;
 
   for (int i = 0; i < ci->children_num; i++) {
     oconfig_item_t *option = ci->children + i;
@@ -794,6 +796,8 @@ static int csnmp_config_add_host(oconfig_item_t *ci) {
       status = csnmp_config_add_host_security_level(hd, option);
     else if (strcasecmp("Context", option->key) == 0)
       status = cf_util_get_string(option, &hd->context);
+    else if (strcasecmp("BulkSize", option->key) == 0)
+      status = cf_util_get_int(option, &hd->bulk_size);
     else {
       WARNING(
           "snmp plugin: csnmp_config_add_host: Option `%s' not allowed here.",
@@ -816,6 +820,11 @@ static int csnmp_config_add_host(oconfig_item_t *ci) {
       status = -1;
       break;
     }
+    if (hd->bulk_size > 0 && hd->version < 2) {
+      WARNING("snmp plugin: Bulk transfers is only available for SNMP v2 and "
+              "later, host '%s' is configured as version '%d'",
+              hd->name, hd->version);
+    }
     if (hd->version == 3) {
       if (hd->username == NULL) {
         WARNING("snmp plugin: `Username' not given for host `%s'", hd->name);
@@ -871,12 +880,13 @@ static int csnmp_config_add_host(oconfig_item_t *ci) {
         "= %i }",
         hd->name, hd->address, hd->community, hd->version);
 
-  snprintf(cb_name, sizeof(cb_name), "snmp-%s", hd->name);
+  ssnprintf(cb_name, sizeof(cb_name), "snmp-%s", hd->name);
 
   status = plugin_register_complex_read(
       /* group = */ NULL, cb_name, csnmp_read_host, interval,
       &(user_data_t){
-          .data = hd, .free_func = csnmp_host_definition_destroy,
+          .data = hd,
+          .free_func = csnmp_host_definition_destroy,
       });
   if (status != 0) {
     ERROR("snmp plugin: Registering complex read function failed.");
@@ -1140,8 +1150,8 @@ static int csnmp_strvbcopy_hexstring(char *dst, /* {{{ */
   for (size_t i = 0; i < vb->val_len; i++) {
     int status;
 
-    status = snprintf(buffer_ptr, buffer_free, (i == 0) ? "%02x" : ":%02x",
-                      (unsigned int)vb->val.bitstring[i]);
+    status = ssnprintf(buffer_ptr, buffer_free, (i == 0) ? "%02x" : ":%02x",
+                       (unsigned int)vb->val.bitstring[i]);
     assert(status >= 0);
 
     if (((size_t)status) >= buffer_free) /* truncated */
@@ -1173,10 +1183,10 @@ static int csnmp_strvbcopy(char *dst, /* {{{ */
   else if (vb->type == ASN_BIT_STR)
     src = (char *)vb->val.bitstring;
   else if (vb->type == ASN_IPADDRESS) {
-    return snprintf(dst, dst_size,
-                    "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "",
-                    (uint8_t)vb->val.string[0], (uint8_t)vb->val.string[1],
-                    (uint8_t)vb->val.string[2], (uint8_t)vb->val.string[3]);
+    return ssnprintf(dst, dst_size,
+                     "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "",
+                     (uint8_t)vb->val.string[0], (uint8_t)vb->val.string[1],
+                     (uint8_t)vb->val.string[2], (uint8_t)vb->val.string[3]);
   } else {
     dst[0] = 0;
     return EINVAL;
@@ -1234,7 +1244,7 @@ static csnmp_cell_char_t *csnmp_get_char_cell(const struct variable_list *vb,
     value_t val = csnmp_value_list_to_value(
         vb, DS_TYPE_COUNTER,
         /* scale = */ 1.0, /* shift = */ 0.0, hd->name, dd->name);
-    snprintf(il->value, sizeof(il->value), "%" PRIu64, (uint64_t)val.counter);
+    ssnprintf(il->value, sizeof(il->value), "%" PRIu64, (uint64_t)val.counter);
   }
 
   return il;
@@ -1479,7 +1489,7 @@ static int csnmp_dispatch_table(host_definition_t *host,
       if (data->host.prefix == NULL)
         sstrncpy(vl.host, temp, sizeof(vl.host));
       else
-        snprintf(vl.host, sizeof(vl.host), "%s%s", data->host.prefix, temp);
+        ssnprintf(vl.host, sizeof(vl.host), "%s%s", data->host.prefix, temp);
     } else {
       sstrncpy(vl.host, host->name, sizeof(vl.host));
     }
@@ -1495,8 +1505,8 @@ static int csnmp_dispatch_table(host_definition_t *host,
       if (data->type_instance.prefix == NULL)
         sstrncpy(vl.type_instance, temp, sizeof(vl.type_instance));
       else
-        snprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
-                 data->type_instance.prefix, temp);
+        ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
+                  data->type_instance.prefix, temp);
     } else if (data->type_instance.value) {
       sstrncpy(vl.type_instance, data->type_instance.value,
                sizeof(vl.type_instance));
@@ -1513,8 +1523,8 @@ static int csnmp_dispatch_table(host_definition_t *host,
       if (data->plugin_instance.prefix == NULL)
         sstrncpy(vl.plugin_instance, temp, sizeof(vl.plugin_instance));
       else
-        snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s%s",
-                 data->plugin_instance.prefix, temp);
+        ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s%s",
+                  data->plugin_instance.prefix, temp);
     } else if (data->plugin_instance.value) {
       sstrncpy(vl.plugin_instance, data->plugin_instance.value,
                sizeof(vl.plugin_instance));
@@ -1654,7 +1664,14 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) {
 
   status = 0;
   while (status == 0) {
-    req = snmp_pdu_create(SNMP_MSG_GETNEXT);
+    /* If SNMP v2 and later and bulk transfers enabled, use GETBULK PDU */
+    if (host->version > 1 && host->bulk_size > 0) {
+      req = snmp_pdu_create(SNMP_MSG_GETBULK);
+      req->non_repeaters = 0;
+      req->max_repetitions = host->bulk_size;
+    } else {
+      req = snmp_pdu_create(SNMP_MSG_GETNEXT);
+    }
     if (req == NULL) {
       ERROR("snmp plugin: snmp_pdu_create failed.");
       status = -1;
@@ -1682,6 +1699,13 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) {
       break;
     }
 
+    if (req->command == SNMP_MSG_GETBULK) {
+      /* In bulk mode the host will send 'max_repetitions' values per
+         requested variable, so we need to split it per number of variable
+         to stay 'in budget' */
+      req->max_repetitions = floor(host->bulk_size / oid_list_todo_num);
+    }
+
     res = NULL;
     status = snmp_sess_synch_response(host->sess_handle, req, &res);
 
@@ -1753,11 +1777,18 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) {
       continue;
     }
 
-    for (vb = res->variables, i = 0; (vb != NULL);
-         vb = vb->next_variable, i++) {
+    size_t j;
+    for (vb = res->variables, j = 0; (vb != NULL);
+         vb = vb->next_variable, j++) {
+      i = j;
+      /* If bulk request is active convert value index of the extra value */
+      if (host->version > 1 && host->bulk_size > 0) {
+        i %= oid_list_todo_num;
+      }
       /* Calculate value index from todo list */
       while ((i < oid_list_len) && !oid_list_todo[i]) {
         i++;
+        j++;
       }
       if (i >= oid_list_len) {
         break;
index cbd3366..bb4a7e4 100644 (file)
@@ -172,7 +172,7 @@ static int snmp_agent_oid_to_string(char *buf, size_t buf_size,
   char *oid_str_ptr[MAX_OID_LEN];
 
   for (size_t i = 0; i < o->oid_len; i++) {
-    snprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
+    ssnprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
     oid_str_ptr[i] = oid_str[i];
   }
 
@@ -736,13 +736,14 @@ static void snmp_agent_table_data_remove(data_definition_t *dd,
   if (index == NULL)
     snmp_agent_oid_to_string(index_str, sizeof(index_str), index_oid);
   else
-    snprintf(index_str, sizeof(index_str), "%d", *index);
+    ssnprintf(index_str, sizeof(index_str), "%d", *index);
 
   notification_t n = {
       .severity = NOTIF_WARNING, .time = cdtime(), .plugin = PLUGIN_NAME};
   sstrncpy(n.host, hostname_g, sizeof(n.host));
-  snprintf(n.message, sizeof(n.message),
-           "Removed data row from table %s with index %s", td->name, index_str);
+  ssnprintf(n.message, sizeof(n.message),
+            "Removed data row from table %s with index %s", td->name,
+            index_str);
   DEBUG(PLUGIN_NAME ": %s", n.message);
   plugin_dispatch_notification(&n);
 
@@ -960,7 +961,7 @@ static int snmp_agent_build_name(char **name, c_avl_tree_t *tokens) {
     strncat(out, tok->str, DATA_MAX_NAME_LEN - strlen(out) - 1);
     if (tok->key != NULL) {
       if (tok->key->type == ASN_INTEGER) {
-        snprintf(str, sizeof(str), "%ld", *tok->key->val.integer);
+        ssnprintf(str, sizeof(str), "%ld", *tok->key->val.integer);
         strncat(out, str, DATA_MAX_NAME_LEN - strlen(out) - 1);
       } else /* OCTET_STR */
         strncat(out, (char *)tok->key->val.string,
@@ -1013,7 +1014,7 @@ static int snmp_agent_format_name(char *name, int name_len,
         }
 
         if (td->index_keys[i].type == ASN_INTEGER) {
-          snprintf(str, sizeof(str), "%ld", *key->val.integer);
+          ssnprintf(str, sizeof(str), "%ld", *key->val.integer);
           fields[source] = str;
         } else /* OCTET_STR */
           fields[source] = (char *)key->val.string;
@@ -1836,7 +1837,7 @@ static int snmp_agent_set_vardata(void *data, size_t *data_len, u_char asn_type,
   case ASN_OCTET_STR:
     if (type == DS_TYPE_GAUGE) {
       char buf[DATA_MAX_NAME_LEN];
-      snprintf(buf, sizeof(buf), "%.2f", val->gauge);
+      ssnprintf(buf, sizeof(buf), "%.2f", val->gauge);
       if (*data_len < strlen(buf))
         return -EINVAL;
       *data_len = strlen(buf);
@@ -1995,13 +1996,13 @@ static int snmp_agent_update_index(data_definition_t *dd,
     if (index == NULL)
       snmp_agent_oid_to_string(index_str, sizeof(index_str), index_oid);
     else
-      snprintf(index_str, sizeof(index_str), "%d", *index);
+      ssnprintf(index_str, sizeof(index_str), "%d", *index);
 
     notification_t n = {
         .severity = NOTIF_OKAY, .time = cdtime(), .plugin = PLUGIN_NAME};
     sstrncpy(n.host, hostname_g, sizeof(n.host));
-    snprintf(n.message, sizeof(n.message),
-             "Data added to table %s with index %s", td->name, index_str);
+    ssnprintf(n.message, sizeof(n.message),
+              "Data added to table %s with index %s", td->name, index_str);
     DEBUG(PLUGIN_NAME ": %s", n.message);
 
     plugin_dispatch_notification(&n);
index 6c7820a..9050596 100644 (file)
@@ -606,9 +606,8 @@ static int statsd_config_timer_percentile(oconfig_item_t *ci) /* {{{ */
     return ERANGE;
   }
 
-  tmp =
-      realloc(conf_timer_percentile,
-              sizeof(*conf_timer_percentile) * (conf_timer_percentile_num + 1));
+  tmp = realloc(conf_timer_percentile, sizeof(*conf_timer_percentile) *
+                                           (conf_timer_percentile_num + 1));
   if (tmp == NULL) {
     ERROR("statsd plugin: realloc failed.");
     return ENOMEM;
index 9e58919..0e317e7 100644 (file)
@@ -49,7 +49,9 @@
 #if HAVE_SYS_PARAM_H
 #include <sys/param.h>
 #endif
-#if HAVE_SYS_SYSCTL_H
+#if (defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME)) ||              \
+    defined(__OpenBSD__)
+/* implies BSD variant */
 #include <sys/sysctl.h>
 #endif
 #if HAVE_SYS_DKSTAT_H
@@ -150,12 +152,12 @@ static int swap_init(void) /* {{{ */
 {
 #if KERNEL_LINUX
   pagesize = (derive_t)sysconf(_SC_PAGESIZE);
-/* #endif KERNEL_LINUX */
+  /* #endif KERNEL_LINUX */
 
 #elif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS
   /* getpagesize(3C) tells me this does not fail.. */
   pagesize = (derive_t)getpagesize();
-/* #endif HAVE_SWAPCTL */
+  /* #endif HAVE_SWAPCTL */
 
 #elif defined(VM_SWAPUSAGE)
 /* No init stuff */
@@ -177,7 +179,7 @@ static int swap_init(void) /* {{{ */
     ERROR("swap plugin: kvm_openfiles failed, %s", errbuf);
     return -1;
   }
-/* #endif HAVE_LIBKVM_GETSWAPINFO */
+    /* #endif HAVE_LIBKVM_GETSWAPINFO */
 
 #elif HAVE_LIBSTATGRAB
 /* No init stuff */
diff --git a/src/sysevent.c b/src/sysevent.c
new file mode 100644 (file)
index 0000000..7f9aa9f
--- /dev/null
@@ -0,0 +1,1148 @@
+/**
+ * collectd - src/sysevent.c
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Red Hat NFVPE
+ *     Andrew Bays <abays at redhat.com>
+ **/
+
+#include "collectd.h"
+
+#include "plugin.h"
+#include "utils/common/common.h"
+#include "utils/ignorelist/ignorelist.h"
+#include "utils_complain.h"
+
+#include <errno.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <regex.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <yajl/yajl_common.h>
+#include <yajl/yajl_gen.h>
+
+#if HAVE_YAJL_YAJL_VERSION_H
+#include <yajl/yajl_version.h>
+#endif
+#if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1)
+#include <yajl/yajl_tree.h>
+#define HAVE_YAJL_V2 1
+#endif
+
+#define SYSEVENT_DOMAIN_FIELD "domain"
+#define SYSEVENT_DOMAIN_VALUE "syslog"
+#define SYSEVENT_EVENT_ID_FIELD "eventId"
+#define SYSEVENT_EVENT_NAME_FIELD "eventName"
+#define SYSEVENT_EVENT_NAME_VALUE "syslog message"
+#define SYSEVENT_LAST_EPOCH_MICROSEC_FIELD "lastEpochMicrosec"
+#define SYSEVENT_PRIORITY_FIELD "priority"
+#define SYSEVENT_PRIORITY_VALUE_HIGH "high"
+#define SYSEVENT_PRIORITY_VALUE_LOW "low"
+#define SYSEVENT_PRIORITY_VALUE_MEDIUM "medium"
+#define SYSEVENT_PRIORITY_VALUE_NORMAL "normal"
+#define SYSEVENT_PRIORITY_VALUE_UNKNOWN "unknown"
+#define SYSEVENT_REPORTING_ENTITY_NAME_FIELD "reportingEntityName"
+#define SYSEVENT_REPORTING_ENTITY_NAME_VALUE "collectd sysevent plugin"
+#define SYSEVENT_SEQUENCE_FIELD "sequence"
+#define SYSEVENT_SEQUENCE_VALUE "0"
+#define SYSEVENT_SOURCE_NAME_FIELD "sourceName"
+#define SYSEVENT_SOURCE_NAME_VALUE "syslog"
+#define SYSEVENT_START_EPOCH_MICROSEC_FIELD "startEpochMicrosec"
+#define SYSEVENT_VERSION_FIELD "version"
+#define SYSEVENT_VERSION_VALUE "1.0"
+
+#define SYSEVENT_EVENT_SOURCE_HOST_FIELD "eventSourceHost"
+#define SYSEVENT_EVENT_SOURCE_TYPE_FIELD "eventSourceType"
+#define SYSEVENT_EVENT_SOURCE_TYPE_VALUE "host"
+#define SYSEVENT_SYSLOG_FIELDS_FIELD "syslogFields"
+#define SYSEVENT_SYSLOG_FIELDS_VERSION_FIELD "syslogFieldsVersion"
+#define SYSEVENT_SYSLOG_FIELDS_VERSION_VALUE "1.0"
+#define SYSEVENT_SYSLOG_MSG_FIELD "syslogMsg"
+#define SYSEVENT_SYSLOG_PROC_FIELD "syslogProc"
+#define SYSEVENT_SYSLOG_SEV_FIELD "syslogSev"
+#define SYSEVENT_SYSLOG_TAG_FIELD "syslogTag"
+#define SYSEVENT_SYSLOG_TAG_VALUE "NILVALUE"
+
+/*
+ * Private data types
+ */
+
+typedef struct {
+  int head;
+  int tail;
+  int maxLen;
+  char **buffer;
+  cdtime_t *timestamp;
+} circbuf_t;
+
+/*
+ * Private variables
+ */
+
+static ignorelist_t *ignorelist = NULL;
+
+static int sysevent_socket_thread_loop = 0;
+static int sysevent_socket_thread_error = 0;
+static pthread_t sysevent_socket_thread_id;
+static int sysevent_dequeue_thread_loop = 0;
+static pthread_t sysevent_dequeue_thread_id;
+static pthread_mutex_t sysevent_thread_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t sysevent_data_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t sysevent_cond = PTHREAD_COND_INITIALIZER;
+static int sock = -1;
+static int event_id = 0;
+static circbuf_t ring;
+
+static char *listen_ip;
+static char *listen_port;
+static int listen_buffer_size = 4096;
+static int buffer_length = 10;
+
+static int monitor_all_messages = 1;
+
+#if HAVE_YAJL_V2
+static const char *rsyslog_keys[3] = {"@timestamp", "@source_host", "@message"};
+static const char *rsyslog_field_keys[5] = {
+    "facility", "severity", "severity-num", "program", "processid"};
+#endif
+
+/*
+ * Private functions
+ */
+
+static int gen_message_payload(const char *msg, char *sev, int sev_num,
+                               char *process, char *host, cdtime_t timestamp,
+                               char **buf) {
+  const unsigned char *buf2;
+  yajl_gen g;
+  char json_str[DATA_MAX_NAME_LEN];
+
+#if !defined(HAVE_YAJL_V2)
+  yajl_gen_config conf = {0};
+#endif
+
+#if HAVE_YAJL_V2
+  size_t len;
+  g = yajl_gen_alloc(NULL);
+  yajl_gen_config(g, yajl_gen_beautify, 0);
+#else
+  unsigned int len;
+  g = yajl_gen_alloc(&conf, NULL);
+#endif
+
+  yajl_gen_clear(g);
+
+  // *** BEGIN common event header ***
+
+  if (yajl_gen_map_open(g) != yajl_gen_status_ok)
+    goto err;
+
+  // domain
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_DOMAIN_FIELD,
+                      strlen(SYSEVENT_DOMAIN_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_DOMAIN_VALUE,
+                      strlen(SYSEVENT_DOMAIN_VALUE)) != yajl_gen_status_ok)
+    goto err;
+
+  // eventId
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_EVENT_ID_FIELD,
+                      strlen(SYSEVENT_EVENT_ID_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  event_id = event_id + 1;
+  snprintf(json_str, sizeof(json_str), "%d", event_id);
+
+  if (yajl_gen_number(g, json_str, strlen(json_str)) != yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // eventName
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_EVENT_NAME_FIELD,
+                      strlen(SYSEVENT_EVENT_NAME_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  snprintf(json_str, sizeof(json_str), "host %s rsyslog message", host);
+
+  if (yajl_gen_string(g, (u_char *)json_str, strlen(json_str)) !=
+      yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // lastEpochMicrosec
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_LAST_EPOCH_MICROSEC_FIELD,
+                      strlen(SYSEVENT_LAST_EPOCH_MICROSEC_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  snprintf(json_str, sizeof(json_str), "%" PRIu64, CDTIME_T_TO_US(cdtime()));
+
+  if (yajl_gen_number(g, json_str, strlen(json_str)) != yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // priority
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_PRIORITY_FIELD,
+                      strlen(SYSEVENT_PRIORITY_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  switch (sev_num) {
+  case 4:
+    if (yajl_gen_string(g, (u_char *)SYSEVENT_PRIORITY_VALUE_MEDIUM,
+                        strlen(SYSEVENT_PRIORITY_VALUE_MEDIUM)) !=
+        yajl_gen_status_ok)
+      goto err;
+    break;
+  case 5:
+    if (yajl_gen_string(g, (u_char *)SYSEVENT_PRIORITY_VALUE_NORMAL,
+                        strlen(SYSEVENT_PRIORITY_VALUE_NORMAL)) !=
+        yajl_gen_status_ok)
+      goto err;
+    break;
+  case 6:
+  case 7:
+    if (yajl_gen_string(g, (u_char *)SYSEVENT_PRIORITY_VALUE_LOW,
+                        strlen(SYSEVENT_PRIORITY_VALUE_LOW)) !=
+        yajl_gen_status_ok)
+      goto err;
+    break;
+  default:
+    if (yajl_gen_string(g, (u_char *)SYSEVENT_PRIORITY_VALUE_UNKNOWN,
+                        strlen(SYSEVENT_PRIORITY_VALUE_UNKNOWN)) !=
+        yajl_gen_status_ok)
+      goto err;
+    break;
+  }
+
+  // reportingEntityName
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_REPORTING_ENTITY_NAME_FIELD,
+                      strlen(SYSEVENT_REPORTING_ENTITY_NAME_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_REPORTING_ENTITY_NAME_VALUE,
+                      strlen(SYSEVENT_REPORTING_ENTITY_NAME_VALUE)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // sequence
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_SEQUENCE_FIELD,
+                      strlen(SYSEVENT_SEQUENCE_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_number(g, SYSEVENT_SEQUENCE_VALUE,
+                      strlen(SYSEVENT_SEQUENCE_VALUE)) != yajl_gen_status_ok)
+    goto err;
+
+  // sourceName
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_SOURCE_NAME_FIELD,
+                      strlen(SYSEVENT_SOURCE_NAME_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_SOURCE_NAME_VALUE,
+                      strlen(SYSEVENT_SOURCE_NAME_VALUE)) != yajl_gen_status_ok)
+    goto err;
+
+  // startEpochMicrosec
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_START_EPOCH_MICROSEC_FIELD,
+                      strlen(SYSEVENT_START_EPOCH_MICROSEC_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  snprintf(json_str, sizeof(json_str), "%" PRIu64, CDTIME_T_TO_US(timestamp));
+
+  if (yajl_gen_number(g, json_str, strlen(json_str)) != yajl_gen_status_ok) {
+    goto err;
+  }
+
+  // version
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_VERSION_FIELD,
+                      strlen(SYSEVENT_VERSION_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_number(g, SYSEVENT_VERSION_VALUE,
+                      strlen(SYSEVENT_VERSION_VALUE)) != yajl_gen_status_ok)
+    goto err;
+
+  // *** END common event header ***
+
+  // *** BEGIN syslog fields ***
+
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_SYSLOG_FIELDS_FIELD,
+                      strlen(SYSEVENT_SYSLOG_FIELDS_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_map_open(g) != yajl_gen_status_ok)
+    goto err;
+
+  // eventSourceHost
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_EVENT_SOURCE_HOST_FIELD,
+                      strlen(SYSEVENT_EVENT_SOURCE_HOST_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)host, strlen(host)) != yajl_gen_status_ok)
+    goto err;
+
+  // eventSourceType
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_EVENT_SOURCE_TYPE_FIELD,
+                      strlen(SYSEVENT_EVENT_SOURCE_TYPE_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_EVENT_SOURCE_TYPE_VALUE,
+                      strlen(SYSEVENT_EVENT_SOURCE_TYPE_VALUE)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // syslogFieldsVersion
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_SYSLOG_FIELDS_VERSION_FIELD,
+                      strlen(SYSEVENT_SYSLOG_FIELDS_VERSION_FIELD)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_number(g, SYSEVENT_SYSLOG_FIELDS_VERSION_VALUE,
+                      strlen(SYSEVENT_SYSLOG_FIELDS_VERSION_VALUE)) !=
+      yajl_gen_status_ok)
+    goto err;
+
+  // syslogMsg
+  if (msg != NULL) {
+    if (yajl_gen_string(g, (u_char *)SYSEVENT_SYSLOG_MSG_FIELD,
+                        strlen(SYSEVENT_SYSLOG_MSG_FIELD)) !=
+        yajl_gen_status_ok)
+      goto err;
+
+    if (yajl_gen_string(g, (u_char *)msg, strlen(msg)) != yajl_gen_status_ok)
+      goto err;
+  }
+
+  // syslogProc
+  if (process != NULL) {
+    if (yajl_gen_string(g, (u_char *)SYSEVENT_SYSLOG_PROC_FIELD,
+                        strlen(SYSEVENT_SYSLOG_PROC_FIELD)) !=
+        yajl_gen_status_ok)
+      goto err;
+
+    if (yajl_gen_string(g, (u_char *)process, strlen(process)) !=
+        yajl_gen_status_ok)
+      goto err;
+  }
+
+  // syslogSev
+  if (sev != NULL) {
+    if (yajl_gen_string(g, (u_char *)SYSEVENT_SYSLOG_SEV_FIELD,
+                        strlen(SYSEVENT_SYSLOG_SEV_FIELD)) !=
+        yajl_gen_status_ok)
+      goto err;
+
+    if (yajl_gen_string(g, (u_char *)sev, strlen(sev)) != yajl_gen_status_ok)
+      goto err;
+  }
+
+  // syslogTag
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_SYSLOG_TAG_FIELD,
+                      strlen(SYSEVENT_SYSLOG_TAG_FIELD)) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_string(g, (u_char *)SYSEVENT_SYSLOG_TAG_VALUE,
+                      strlen(SYSEVENT_SYSLOG_TAG_VALUE)) != yajl_gen_status_ok)
+    goto err;
+
+  // *** END syslog fields ***
+
+  // close syslog and header fields
+  if (yajl_gen_map_close(g) != yajl_gen_status_ok ||
+      yajl_gen_map_close(g) != yajl_gen_status_ok)
+    goto err;
+
+  if (yajl_gen_get_buf(g, &buf2, &len) != yajl_gen_status_ok)
+    goto err;
+
+  *buf = strdup((char *)buf2);
+
+  if (*buf == NULL) {
+    ERROR("sysevent plugin: gen_message_payload strdup failed");
+    goto err;
+  }
+
+  yajl_gen_free(g);
+
+  return 0;
+
+err:
+  yajl_gen_free(g);
+  ERROR("sysevent plugin: gen_message_payload failed to generate JSON");
+  return -1;
+}
+
+static int read_socket() {
+  int recv_flags = MSG_DONTWAIT;
+
+  while (42) {
+    struct sockaddr_storage src_addr;
+    socklen_t src_addr_len = sizeof(src_addr);
+
+    char buffer[listen_buffer_size];
+    memset(buffer, '\0', listen_buffer_size);
+
+    ssize_t count = recvfrom(sock, buffer, sizeof(buffer), recv_flags,
+                             (struct sockaddr *)&src_addr, &src_addr_len);
+
+    if (count < 0) {
+      if (errno == EAGAIN || errno == EWOULDBLOCK) {
+        pthread_mutex_lock(&sysevent_data_lock);
+
+        // There was nothing more to receive for now, so...
+        // If ring head does not equal ring tail, there is data
+        // in the ring buffer for the dequeue thread to read, so
+        // signal it
+        if (ring.head != ring.tail)
+          pthread_cond_signal(&sysevent_cond);
+
+        pthread_mutex_unlock(&sysevent_data_lock);
+
+        // Since there was nothing to receive, set recv to block and
+        // try again
+        recv_flags = 0;
+        continue;
+      } else if (errno != EINTR) {
+        ERROR("sysevent plugin: failed to receive data: %s", STRERRNO);
+        return -1;
+      } else {
+        // Interrupt, so continue and try again
+        continue;
+      }
+    }
+
+    if (count >= sizeof(buffer)) {
+      WARNING("sysevent plugin: datagram too large for buffer: truncated");
+    }
+
+    // We successfully received a message, so don't block on the next
+    // read in case there are more (and if there aren't, it will be
+    // handled above in the EWOULDBLOCK error-checking)
+    recv_flags = MSG_DONTWAIT;
+
+    // 1. Acquire data lock
+    // 2. Push to buffer if there is room, otherwise raise warning
+    //    and allow dequeue thread to take over
+
+    pthread_mutex_lock(&sysevent_data_lock);
+
+    int next = ring.head + 1;
+    if (next >= ring.maxLen)
+      next = 0;
+
+    if (next == ring.tail) {
+      // Buffer is full, signal the dequeue thread to process the buffer
+      // and clean it out, and then sleep
+      WARNING("sysevent plugin: ring buffer full");
+
+      pthread_cond_signal(&sysevent_cond);
+      pthread_mutex_unlock(&sysevent_data_lock);
+
+      usleep(1000);
+      continue;
+    } else {
+      DEBUG("sysevent plugin: writing %s", buffer);
+
+      sstrncpy(ring.buffer[ring.head], buffer, sizeof(buffer));
+      ring.timestamp[ring.head] = cdtime();
+      ring.head = next;
+    }
+
+    pthread_mutex_unlock(&sysevent_data_lock);
+  }
+}
+
+static void sysevent_dispatch_notification(const char *message,
+#if HAVE_YAJL_V2
+                                           yajl_val *node,
+#endif
+                                           cdtime_t timestamp) {
+  char *buf = NULL;
+
+  notification_t n = {
+      .severity = NOTIF_OKAY,
+      .time = cdtime(),
+      .plugin = "sysevent",
+      .type = "gauge",
+  };
+
+#if HAVE_YAJL_V2
+  if (node != NULL) {
+    // If we have a parsed-JSON node to work with, use that
+    // msg
+    const char *msg_path[] = {rsyslog_keys[2], (const char *)0};
+    yajl_val msg_v = yajl_tree_get(*node, msg_path, yajl_t_string);
+
+    char msg[listen_buffer_size];
+
+    if (msg_v != NULL) {
+      memset(msg, '\0', listen_buffer_size);
+      snprintf(msg, listen_buffer_size, "%s%c", YAJL_GET_STRING(msg_v), '\0');
+    }
+
+    // severity
+    const char *severity_path[] = {"@fields", rsyslog_field_keys[1],
+                                   (const char *)0};
+    yajl_val severity_v = yajl_tree_get(*node, severity_path, yajl_t_string);
+
+    char severity[listen_buffer_size];
+
+    if (severity_v != NULL) {
+      memset(severity, '\0', listen_buffer_size);
+      snprintf(severity, listen_buffer_size, "%s%c",
+               YAJL_GET_STRING(severity_v), '\0');
+    }
+
+    // sev_num
+    const char *sev_num_str_path[] = {"@fields", rsyslog_field_keys[2],
+                                      (const char *)0};
+    yajl_val sev_num_str_v =
+        yajl_tree_get(*node, sev_num_str_path, yajl_t_string);
+
+    char sev_num_str[listen_buffer_size];
+    int sev_num = -1;
+
+    if (sev_num_str_v != NULL) {
+      memset(sev_num_str, '\0', listen_buffer_size);
+      snprintf(sev_num_str, listen_buffer_size, "%s%c",
+               YAJL_GET_STRING(sev_num_str_v), '\0');
+
+      sev_num = atoi(sev_num_str);
+
+      if (sev_num < 4)
+        n.severity = NOTIF_FAILURE;
+    }
+
+    // process
+    const char *process_path[] = {"@fields", rsyslog_field_keys[3],
+                                  (const char *)0};
+    yajl_val process_v = yajl_tree_get(*node, process_path, yajl_t_string);
+
+    char process[listen_buffer_size];
+
+    if (process_v != NULL) {
+      memset(process, '\0', listen_buffer_size);
+      snprintf(process, listen_buffer_size, "%s%c", YAJL_GET_STRING(process_v),
+               '\0');
+    }
+
+    // hostname
+    const char *hostname_path[] = {rsyslog_keys[1], (const char *)0};
+    yajl_val hostname_v = yajl_tree_get(*node, hostname_path, yajl_t_string);
+
+    char hostname_str[listen_buffer_size];
+
+    if (hostname_v != NULL) {
+      memset(hostname_str, '\0', listen_buffer_size);
+      snprintf(hostname_str, listen_buffer_size, "%s%c",
+               YAJL_GET_STRING(hostname_v), '\0');
+    }
+
+    gen_message_payload(
+        (msg_v != NULL ? msg : NULL), (severity_v != NULL ? severity : NULL),
+        (sev_num_str_v != NULL ? sev_num : -1),
+        (process_v != NULL ? process : NULL),
+        (hostname_v != NULL ? hostname_str : hostname_g), timestamp, &buf);
+  } else {
+    // Data was not sent in JSON format, so just treat the whole log entry
+    // as the message (and we'll be unable to acquire certain data, so the
+    // payload
+    // generated below will be less informative)
+
+    gen_message_payload(message, NULL, -1, NULL, hostname_g, timestamp, &buf);
+  }
+#else
+  gen_message_payload(message, NULL, -1, NULL, hostname_g, timestamp, &buf);
+#endif
+
+  sstrncpy(n.host, hostname_g, sizeof(n.host));
+
+  int status = plugin_notification_meta_add_string(&n, "ves", buf);
+
+  if (status < 0) {
+    sfree(buf);
+    ERROR("sysevent plugin: unable to set notification VES metadata: %s",
+          STRERRNO);
+    return;
+  }
+
+  DEBUG("sysevent plugin: notification VES metadata: %s",
+        n.meta->nm_value.nm_string);
+
+  DEBUG("sysevent plugin: dispatching message");
+
+  plugin_dispatch_notification(&n);
+  plugin_notification_meta_free(n.meta);
+
+  // strdup'd in gen_message_payload
+  if (buf != NULL)
+    sfree(buf);
+}
+
+static void read_ring_buffer() {
+  pthread_mutex_lock(&sysevent_data_lock);
+
+  // If there's currently nothing to read from the buffer,
+  // then wait
+  if (ring.head == ring.tail)
+    pthread_cond_wait(&sysevent_cond, &sysevent_data_lock);
+
+  while (ring.head != ring.tail) {
+    int next = ring.tail + 1;
+
+    if (next >= ring.maxLen)
+      next = 0;
+
+    DEBUG("sysevent plugin: reading from ring buffer: %s",
+          ring.buffer[ring.tail]);
+
+    cdtime_t timestamp = ring.timestamp[ring.tail];
+    char *match_str = NULL;
+
+#if HAVE_YAJL_V2
+    // Try to parse JSON, and if it fails, fall back to plain string
+    char errbuf[1024];
+    errbuf[0] = 0;
+    yajl_val node = yajl_tree_parse((const char *)ring.buffer[ring.tail],
+                                    errbuf, sizeof(errbuf));
+
+    if (node != NULL) {
+      // JSON rsyslog data
+
+      // If we have any regex filters, we need to see if the message portion of
+      // the data matches any of them (otherwise we're not interested)
+      if (monitor_all_messages == 0) {
+        const char *path[] = {"@message", (const char *)0};
+        yajl_val v = yajl_tree_get(node, path, yajl_t_string);
+
+        char json_val[listen_buffer_size];
+        memset(json_val, '\0', listen_buffer_size);
+
+        snprintf(json_val, listen_buffer_size, "%s%c", YAJL_GET_STRING(v),
+                 '\0');
+
+        match_str = (char *)&json_val;
+      }
+    } else {
+      // non-JSON rsyslog data
+
+      // If we have any regex filters, we need to see if the message data
+      // matches any of them (otherwise we're not interested)
+      if (monitor_all_messages == 0)
+        match_str = ring.buffer[ring.tail];
+    }
+#else
+    // If we have any regex filters, we need to see if the message data
+    // matches any of them (otherwise we're not interested)
+    if (monitor_all_messages == 0)
+      match_str = ring.buffer[ring.tail];
+#endif
+
+    int is_match = 1;
+
+    // If we care about matching, do that comparison here
+    if (match_str != NULL) {
+      if (ignorelist_match(ignorelist, match_str) != 0)
+        is_match = 0;
+      else
+        DEBUG("sysevent plugin: regex filter match");
+    }
+
+#if HAVE_YAJL_V2
+    if (is_match == 1 && node != NULL) {
+      sysevent_dispatch_notification(NULL, &node, timestamp);
+      yajl_tree_free(node);
+    } else if (is_match == 1)
+      sysevent_dispatch_notification(ring.buffer[ring.tail], NULL, timestamp);
+#else
+    if (is_match == 1)
+      sysevent_dispatch_notification(ring.buffer[ring.tail], timestamp);
+#endif
+
+    ring.tail = next;
+  }
+
+  pthread_mutex_unlock(&sysevent_data_lock);
+}
+
+static void *sysevent_socket_thread(void *arg) /* {{{ */
+{
+  pthread_mutex_lock(&sysevent_thread_lock);
+
+  while (sysevent_socket_thread_loop > 0) {
+    pthread_mutex_unlock(&sysevent_thread_lock);
+
+    if (sock == -1)
+      return (void *)0;
+
+    int status = read_socket();
+
+    pthread_mutex_lock(&sysevent_thread_lock);
+
+    if (status < 0) {
+      WARNING("sysevent plugin: problem with socket thread (status: %d)",
+              status);
+      sysevent_socket_thread_error = 1;
+      break;
+    }
+  } /* while (sysevent_socket_thread_loop > 0) */
+
+  pthread_mutex_unlock(&sysevent_thread_lock);
+
+  return (void *)0;
+} /* }}} void *sysevent_socket_thread */
+
+// Entry point for thread responsible for reading from
+// ring buffer and dispatching notifications
+static void *sysevent_dequeue_thread(void *arg) /* {{{ */
+{
+  pthread_mutex_lock(&sysevent_thread_lock);
+
+  while (sysevent_dequeue_thread_loop > 0) {
+    pthread_mutex_unlock(&sysevent_thread_lock);
+
+    read_ring_buffer();
+
+    pthread_mutex_lock(&sysevent_thread_lock);
+  } /* while (sysevent_dequeue_thread_loop > 0) */
+
+  pthread_mutex_unlock(&sysevent_thread_lock);
+
+  return (void *)0;
+} /* }}} void *sysevent_dequeue_thread */
+
+static int start_socket_thread(void) /* {{{ */
+{
+  pthread_mutex_lock(&sysevent_thread_lock);
+
+  if (sysevent_socket_thread_loop != 0) {
+    pthread_mutex_unlock(&sysevent_thread_lock);
+    return 0;
+  }
+
+  sysevent_socket_thread_loop = 1;
+  sysevent_socket_thread_error = 0;
+
+  DEBUG("sysevent plugin: starting socket thread");
+
+  int status = plugin_thread_create(&sysevent_socket_thread_id,
+                                    /* attr = */ NULL, sysevent_socket_thread,
+                                    /* arg = */ (void *)0, "sysevent");
+  if (status != 0) {
+    sysevent_socket_thread_loop = 0;
+    ERROR("sysevent plugin: starting socket thread failed.");
+    pthread_mutex_unlock(&sysevent_thread_lock);
+    return -1;
+  }
+
+  pthread_mutex_unlock(&sysevent_thread_lock);
+
+  return 0;
+} /* }}} int start_socket_thread */
+
+static int start_dequeue_thread(void) /* {{{ */
+{
+  pthread_mutex_lock(&sysevent_thread_lock);
+
+  if (sysevent_dequeue_thread_loop != 0) {
+    pthread_mutex_unlock(&sysevent_thread_lock);
+    return 0;
+  }
+
+  sysevent_dequeue_thread_loop = 1;
+
+  int status = plugin_thread_create(&sysevent_dequeue_thread_id,
+                                    /* attr = */ NULL, sysevent_dequeue_thread,
+                                    /* arg = */ (void *)0, "ssyevent");
+  if (status != 0) {
+    sysevent_dequeue_thread_loop = 0;
+    ERROR("sysevent plugin: Starting dequeue thread failed.");
+    pthread_mutex_unlock(&sysevent_thread_lock);
+    return -1;
+  }
+
+  pthread_mutex_unlock(&sysevent_thread_lock);
+
+  return status;
+} /* }}} int start_dequeue_thread */
+
+static int start_threads(void) /* {{{ */
+{
+  int status = start_socket_thread();
+  int status2 = start_dequeue_thread();
+
+  if (status != 0)
+    return status;
+  else
+    return status2;
+} /* }}} int start_threads */
+
+static int stop_socket_thread(int shutdown) /* {{{ */
+{
+  pthread_mutex_lock(&sysevent_thread_lock);
+
+  if (sysevent_socket_thread_loop == 0) {
+    pthread_mutex_unlock(&sysevent_thread_lock);
+    return -1;
+  }
+
+  sysevent_socket_thread_loop = 0;
+  pthread_cond_broadcast(&sysevent_cond);
+  pthread_mutex_unlock(&sysevent_thread_lock);
+
+  int status;
+
+  if (shutdown == 1) {
+    // Since the thread is blocking, calling pthread_join
+    // doesn't actually succeed in stopping it.  It will stick around
+    // until a message is received on the socket (at which
+    // it will realize that "sysevent_socket_thread_loop" is 0 and will
+    // break out of the read loop and be allowed to die).  This is
+    // fine when the process isn't supposed to be exiting, but in
+    // the case of a process shutdown, we don't want to have an
+    // idle thread hanging around.  Calling pthread_cancel here in
+    // the case of a shutdown is just assures that the thread is
+    // gone and that the process has been fully terminated.
+
+    DEBUG("sysevent plugin: Canceling socket thread for process shutdown");
+
+    status = pthread_cancel(sysevent_socket_thread_id);
+
+    if (status != 0 && status != ESRCH) {
+      ERROR("sysevent plugin: Unable to cancel socket thread: %d (%s)", status,
+            STRERRNO);
+      status = -1;
+    } else
+      status = 0;
+  } else {
+    status = pthread_join(sysevent_socket_thread_id, /* return = */ NULL);
+    if (status != 0 && status != ESRCH) {
+      ERROR("sysevent plugin: Stopping socket thread failed.");
+      status = -1;
+    } else
+      status = 0;
+  }
+
+  pthread_mutex_lock(&sysevent_thread_lock);
+  memset(&sysevent_socket_thread_id, 0, sizeof(sysevent_socket_thread_id));
+  sysevent_socket_thread_error = 0;
+  pthread_mutex_unlock(&sysevent_thread_lock);
+
+  DEBUG("sysevent plugin: Finished requesting stop of socket thread");
+
+  return status;
+} /* }}} int stop_socket_thread */
+
+static int stop_dequeue_thread() /* {{{ */
+{
+  pthread_mutex_lock(&sysevent_thread_lock);
+
+  if (sysevent_dequeue_thread_loop == 0) {
+    pthread_mutex_unlock(&sysevent_thread_lock);
+    return -1;
+  }
+
+  sysevent_dequeue_thread_loop = 0;
+  pthread_cond_broadcast(&sysevent_cond);
+  pthread_mutex_unlock(&sysevent_thread_lock);
+
+  // Since the thread is blocking, calling pthread_join
+  // doesn't actually succeed in stopping it.  It will stick around
+  // until a message is received on the socket (at which
+  // it will realize that "sysevent_dequeue_thread_loop" is 0 and will
+  // break out of the read loop and be allowed to die).  Since this
+  // function is called when the processing is exiting, we don't want to
+  // have an idle thread hanging around.  Calling pthread_cancel here
+  // just assures that the thread is gone and that the process has been
+  // fully terminated.
+
+  DEBUG("sysevent plugin: Canceling dequeue thread for process shutdown");
+
+  int status = pthread_cancel(sysevent_dequeue_thread_id);
+
+  if (status != 0 && status != ESRCH) {
+    ERROR("sysevent plugin: Unable to cancel dequeue thread: %d (%s)", status,
+          STRERRNO);
+    status = -1;
+  } else
+    status = 0;
+
+  pthread_mutex_lock(&sysevent_thread_lock);
+  memset(&sysevent_dequeue_thread_id, 0, sizeof(sysevent_dequeue_thread_id));
+  pthread_mutex_unlock(&sysevent_thread_lock);
+
+  DEBUG("sysevent plugin: Finished requesting stop of dequeue thread");
+
+  return status;
+} /* }}} int stop_dequeue_thread */
+
+static int stop_threads() /* {{{ */
+{
+  int status = stop_socket_thread(1);
+  int status2 = stop_dequeue_thread();
+
+  if (status != 0)
+    return status;
+  else
+    return status2;
+} /* }}} int stop_threads */
+
+static int sysevent_init(void) /* {{{ */
+{
+  ring.head = 0;
+  ring.tail = 0;
+  ring.maxLen = buffer_length;
+  ring.buffer = (char **)calloc(buffer_length, sizeof(char *));
+
+  if (ring.buffer == NULL) {
+    ERROR("sysevent plugin: sysevent_init ring buffer calloc failed");
+    return -1;
+  }
+
+  for (int i = 0; i < buffer_length; i++) {
+    ring.buffer[i] = calloc(1, listen_buffer_size);
+
+    if (ring.buffer[i] == NULL) {
+      ERROR("sysevent plugin: sysevent_init ring buffer entry calloc failed");
+      return -1;
+    }
+  }
+
+  ring.timestamp = (cdtime_t *)calloc(buffer_length, sizeof(cdtime_t));
+
+  if (ring.timestamp == NULL) {
+    ERROR("sysevent plugin: sysevent_init ring buffer timestamp calloc failed");
+    return -1;
+  }
+
+  if (sock == -1) {
+    struct addrinfo hints = {
+        .ai_family = AF_UNSPEC,
+        .ai_socktype = SOCK_DGRAM,
+        .ai_protocol = 0,
+        .ai_flags = AI_PASSIVE | AI_ADDRCONFIG,
+    };
+    struct addrinfo *res = 0;
+
+    int err = getaddrinfo(listen_ip, listen_port, &hints, &res);
+
+    if (err != 0) {
+      ERROR("sysevent plugin: failed to resolve local socket address (err=%d)",
+            err);
+      freeaddrinfo(res);
+      return -1;
+    }
+
+    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+    if (sock == -1) {
+      ERROR("sysevent plugin: failed to open socket: %s", STRERRNO);
+      freeaddrinfo(res);
+      return -1;
+    }
+
+    if (bind(sock, res->ai_addr, res->ai_addrlen) == -1) {
+      ERROR("sysevent plugin: failed to bind socket: %s", STRERRNO);
+      freeaddrinfo(res);
+      sock = -1;
+      return -1;
+    }
+
+    freeaddrinfo(res);
+  }
+
+  DEBUG("sysevent plugin: socket created and bound");
+
+  return start_threads();
+} /* }}} int sysevent_init */
+
+static int sysevent_config_add_listen(const oconfig_item_t *ci) /* {{{ */
+{
+  if (ci->values_num != 2 || ci->values[0].type != OCONFIG_TYPE_STRING ||
+      ci->values[1].type != OCONFIG_TYPE_STRING) {
+    ERROR("sysevent plugin: The `%s' config option needs "
+          "two string arguments (ip and port).",
+          ci->key);
+    return -1;
+  }
+
+  listen_ip = strdup(ci->values[0].value.string);
+  listen_port = strdup(ci->values[1].value.string);
+
+  return 0;
+}
+
+static int sysevent_config_add_buffer_size(const oconfig_item_t *ci) /* {{{ */
+{
+  int tmp = 0;
+
+  if (cf_util_get_int(ci, &tmp) != 0)
+    return -1;
+  else if ((tmp >= 1024) && (tmp <= 65535))
+    listen_buffer_size = tmp;
+  else {
+    WARNING(
+        "sysevent plugin: The `BufferSize' must be between 1024 and 65535.");
+    return -1;
+  }
+
+  return 0;
+}
+
+static int sysevent_config_add_buffer_length(const oconfig_item_t *ci) /* {{{ */
+{
+  int tmp = 0;
+
+  if (cf_util_get_int(ci, &tmp) != 0)
+    return -1;
+  else if ((tmp >= 3) && (tmp <= 4096))
+    buffer_length = tmp;
+  else {
+    WARNING("sysevent plugin: The `Bufferlength' must be between 3 and 4096.");
+    return -1;
+  }
+
+  return 0;
+}
+
+static int sysevent_config_add_regex_filter(const oconfig_item_t *ci) /* {{{ */
+{
+  if (ci->values_num != 1 || ci->values[0].type != OCONFIG_TYPE_STRING) {
+    ERROR("sysevent plugin: The `%s' config option needs "
+          "one string argument, a regular expression.",
+          ci->key);
+    return -1;
+  }
+
+#if HAVE_REGEX_H
+  if (ignorelist == NULL)
+    ignorelist = ignorelist_create(/* invert = */ 1);
+
+  int status = ignorelist_add(ignorelist, ci->values[0].value.string);
+
+  if (status != 0) {
+    ERROR("sysevent plugin: invalid regular expression: %s",
+          ci->values[0].value.string);
+    return 1;
+  }
+
+  monitor_all_messages = 0;
+#else
+  WARNING("sysevent plugin: The plugin has been compiled without support "
+          "for the \"RegexFilter\" option.");
+#endif
+
+  return 0;
+}
+
+static int sysevent_config(oconfig_item_t *ci) /* {{{ */
+{
+  for (int i = 0; i < ci->children_num; i++) {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp("Listen", child->key) == 0)
+      sysevent_config_add_listen(child);
+    else if (strcasecmp("BufferSize", child->key) == 0)
+      sysevent_config_add_buffer_size(child);
+    else if (strcasecmp("BufferLength", child->key) == 0)
+      sysevent_config_add_buffer_length(child);
+    else if (strcasecmp("RegexFilter", child->key) == 0)
+      sysevent_config_add_regex_filter(child);
+    else {
+      WARNING("sysevent plugin: Option `%s' is not allowed here.", child->key);
+    }
+  }
+
+  return 0;
+} /* }}} int sysevent_config */
+
+static int sysevent_read(void) /* {{{ */
+{
+  pthread_mutex_lock(&sysevent_thread_lock);
+
+  if (sysevent_socket_thread_error != 0) {
+    pthread_mutex_unlock(&sysevent_thread_lock);
+
+    ERROR("sysevent plugin: The sysevent socket thread had a problem (%d). "
+          "Restarting it.",
+          sysevent_socket_thread_error);
+
+    stop_threads();
+
+    start_threads();
+
+    return -1;
+  } /* if (sysevent_socket_thread_error != 0) */
+
+  pthread_mutex_unlock(&sysevent_thread_lock);
+
+  return 0;
+} /* }}} int sysevent_read */
+
+static int sysevent_shutdown(void) /* {{{ */
+{
+  DEBUG("sysevent plugin: Shutting down thread.");
+
+  int status = stop_threads();
+  int status2 = 0;
+
+  if (sock != -1) {
+    status2 = close(sock);
+    if (status2 != 0) {
+      ERROR("sysevent plugin: failed to close socket %d: %d (%s)", sock, status,
+            STRERRNO);
+    }
+
+    sock = -1;
+  }
+
+  free(listen_ip);
+  free(listen_port);
+
+  for (int i = 0; i < buffer_length; i++) {
+    free(ring.buffer[i]);
+  }
+
+  free(ring.buffer);
+  free(ring.timestamp);
+
+  if (status != 0)
+    return status;
+  else
+    return status2;
+} /* }}} int sysevent_shutdown */
+
+void module_register(void) {
+  plugin_register_complex_config("sysevent", sysevent_config);
+  plugin_register_init("sysevent", sysevent_init);
+  plugin_register_read("sysevent", sysevent_read);
+  plugin_register_shutdown("sysevent", sysevent_shutdown);
+} /* void module_register */
index a600f30..ee3d9f9 100644 (file)
@@ -41,7 +41,8 @@ static int log_level = LOG_INFO;
 static int notif_severity;
 
 static const char *config_keys[] = {
-    "LogLevel", "NotifyLevel",
+    "LogLevel",
+    "NotifyLevel",
 };
 static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
 
@@ -50,13 +51,14 @@ static int sl_config(const char *key, const char *value) {
     log_level = parse_log_severity(value);
     if (log_level < 0) {
       log_level = LOG_INFO;
-      ERROR("syslog: invalid loglevel [%s] defaulting to 'info'", value);
-      return 1;
+      WARNING("syslog: invalid loglevel [%s] defaulting to 'info'", value);
     }
   } else if (strcasecmp(key, "NotifyLevel") == 0) {
     notif_severity = parse_notif_severity(value);
-    if (notif_severity < 0)
+    if (notif_severity < 0) {
+      ERROR("syslog: invalid notification severity [%s]", value);
       return 1;
+    }
   }
 
   return 0;
index e1d473e..ab8bf6d 100644 (file)
@@ -482,7 +482,8 @@ static int tcsv_config_add_file(oconfig_item_t *ci) {
   status = plugin_register_complex_read(
       NULL, cb_name, tcsv_read, interval,
       &(user_data_t){
-          .data = id, .free_func = tcsv_instance_definition_destroy,
+          .data = id,
+          .free_func = tcsv_instance_definition_destroy,
       });
   if (status != 0) {
     ERROR("tail_csv plugin: Registering complex read function failed.");
index ccf8825..c95ebfb 100644 (file)
@@ -63,7 +63,8 @@ static void tape_submit(const char *plugin_instance, const char *type,
                         derive_t read, derive_t write) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = read}, {.derive = write},
+      {.derive = read},
+      {.derive = write},
   };
 
   vl.values = values;
index d01bcd2..ae08b88 100644 (file)
@@ -413,7 +413,7 @@ static int conn_handle_ports(uint16_t port_local, uint16_t port_remote,
 #if TCP_STATE_MIN > 0
       || (state < TCP_STATE_MIN)
 #endif
-          ) {
+  ) {
     NOTICE("tcpconns plugin: Ignoring connection with "
            "unknown state 0x%02" PRIx8 ".",
            state);
@@ -630,10 +630,10 @@ static int conn_read_file(const char *file) {
 
   return 0;
 } /* int conn_read_file */
-/* #endif KERNEL_LINUX */
+  /* #endif KERNEL_LINUX */
 
 #elif HAVE_SYSCTLBYNAME
-/* #endif HAVE_SYSCTLBYNAME */
+  /* #endif HAVE_SYSCTLBYNAME */
 
 #elif HAVE_LIBKVM_NLIST
 #endif /* HAVE_LIBKVM_NLIST */
@@ -729,7 +729,7 @@ static int conn_read(void) {
 
   return 0;
 } /* int conn_read */
-/* #endif KERNEL_LINUX */
+  /* #endif KERNEL_LINUX */
 
 #elif HAVE_SYSCTLBYNAME
 static int conn_read(void) {
@@ -848,8 +848,8 @@ static int conn_read(void) {
 
   return 0;
 }
-/* int conn_read */
-/* #endif HAVE_KVM_GETFILES */
+  /* int conn_read */
+  /* #endif HAVE_KVM_GETFILES */
 
 #elif HAVE_LIBKVM_NLIST
 static int kread(u_long addr, void *buf, int size) {
@@ -966,7 +966,7 @@ static int conn_read(void) {
 
   return 0;
 }
-/* #endif HAVE_LIBKVM_NLIST */
+  /* #endif HAVE_LIBKVM_NLIST */
 
 #elif KERNEL_AIX
 
index 1ab6e4b..42cc54e 100644 (file)
@@ -132,7 +132,8 @@ static void tss2_submit_io(const char *plugin_instance, const char *type,
    */
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = rx}, {.derive = tx},
+      {.derive = rx},
+      {.derive = tx},
   };
 
   vl.values = values;
index e1b48fd..ff650a8 100644 (file)
--- a/src/ted.c
+++ b/src/ted.c
@@ -243,7 +243,7 @@ static int ted_config(const char *key, const char *value) {
 
     tmp = atoi(value);
     if (tmp < 0) {
-      WARNING("ted plugin: Invalid retry count: %i", tmp);
+      ERROR("ted plugin: Invalid retry count: %i", tmp);
       return 1;
     }
     conf_retries = tmp;
index 5f44836..1ed5617 100644 (file)
@@ -103,7 +103,7 @@ static int thermal_procfs_device_read(const char __attribute__((unused)) * dir,
   if ((len < 0) || ((size_t)len >= sizeof(filename)))
     return -1;
 
-  len = (ssize_t)read_file_contents(filename, data, sizeof(data));
+  len = (ssize_t)read_text_file_contents(filename, data, sizeof(data));
   if ((len > 0) && ((size_t)len > sizeof(str_temp)) && (data[--len] == '\n') &&
       (!strncmp(data, str_temp, sizeof(str_temp) - 1))) {
     char *endptr = NULL;
index a3d865b..e74dfc2 100644 (file)
@@ -335,22 +335,22 @@ static int ut_report_state(const data_set_t *ds, const value_list_t *vl,
 
   n.time = vl->time;
 
-  status = snprintf(buf, bufsize, "Host %s, plugin %s", vl->host, vl->plugin);
+  status = ssnprintf(buf, bufsize, "Host %s, plugin %s", vl->host, vl->plugin);
   buf += status;
   bufsize -= status;
 
   if (vl->plugin_instance[0] != '\0') {
-    status = snprintf(buf, bufsize, " (instance %s)", vl->plugin_instance);
+    status = ssnprintf(buf, bufsize, " (instance %s)", vl->plugin_instance);
     buf += status;
     bufsize -= status;
   }
 
-  status = snprintf(buf, bufsize, " type %s", vl->type);
+  status = ssnprintf(buf, bufsize, " type %s", vl->type);
   buf += status;
   bufsize -= status;
 
   if (vl->type_instance[0] != '\0') {
-    status = snprintf(buf, bufsize, " (instance %s)", vl->type_instance);
+    status = ssnprintf(buf, bufsize, " (instance %s)", vl->type_instance);
     buf += status;
     bufsize -= status;
   }
@@ -365,11 +365,12 @@ static int ut_report_state(const data_set_t *ds, const value_list_t *vl,
   /* Send an okay notification */
   if (state == STATE_OKAY) {
     if (state_old == STATE_MISSING)
-      snprintf(buf, bufsize, ": Value is no longer missing.");
+      ssnprintf(buf, bufsize, ": Value is no longer missing.");
     else
-      snprintf(buf, bufsize, ": All data sources are within range again. "
-                             "Current value of \"%s\" is %f.",
-               ds->ds[ds_index].name, values[ds_index]);
+      ssnprintf(buf, bufsize,
+                ": All data sources are within range again. "
+                "Current value of \"%s\" is %f.",
+                ds->ds[ds_index].name, values[ds_index]);
   } else if (state == STATE_UNKNOWN) {
     ERROR("ut_report_state: metric transition to UNKNOWN from a different "
           "state. This shouldn't happen.");
@@ -383,21 +384,22 @@ static int ut_report_state(const data_set_t *ds, const value_list_t *vl,
 
     if (th->flags & UT_FLAG_INVERT) {
       if (!isnan(min) && !isnan(max)) {
-        snprintf(buf, bufsize,
-                 ": Data source \"%s\" is currently "
-                 "%f. That is within the %s region of %f%s and %f%s.",
-                 ds->ds[ds_index].name, values[ds_index],
-                 (state == STATE_ERROR) ? "failure" : "warning", min,
-                 ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "", max,
-                 ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "");
+        ssnprintf(buf, bufsize,
+                  ": Data source \"%s\" is currently "
+                  "%f. That is within the %s region of %f%s and %f%s.",
+                  ds->ds[ds_index].name, values[ds_index],
+                  (state == STATE_ERROR) ? "failure" : "warning", min,
+                  ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "", max,
+                  ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "");
       } else {
-        snprintf(buf, bufsize, ": Data source \"%s\" is currently "
-                               "%f. That is %s the %s threshold of %f%s.",
-                 ds->ds[ds_index].name, values[ds_index],
-                 isnan(min) ? "below" : "above",
-                 (state == STATE_ERROR) ? "failure" : "warning",
-                 isnan(min) ? max : min,
-                 ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "");
+        ssnprintf(buf, bufsize,
+                  ": Data source \"%s\" is currently "
+                  "%f. That is %s the %s threshold of %f%s.",
+                  ds->ds[ds_index].name, values[ds_index],
+                  isnan(min) ? "below" : "above",
+                  (state == STATE_ERROR) ? "failure" : "warning",
+                  isnan(min) ? max : min,
+                  ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "");
       }
     } else if (th->flags & UT_FLAG_PERCENTAGE) {
       gauge_t value;
@@ -416,21 +418,22 @@ static int ut_report_state(const data_set_t *ds, const value_list_t *vl,
       else
         value = 100.0 * values[ds_index] / sum;
 
-      snprintf(buf, bufsize,
-               ": Data source \"%s\" is currently "
-               "%g (%.2f%%). That is %s the %s threshold of %.2f%%.",
-               ds->ds[ds_index].name, values[ds_index], value,
-               (value < min) ? "below" : "above",
-               (state == STATE_ERROR) ? "failure" : "warning",
-               (value < min) ? min : max);
+      ssnprintf(buf, bufsize,
+                ": Data source \"%s\" is currently "
+                "%g (%.2f%%). That is %s the %s threshold of %.2f%%.",
+                ds->ds[ds_index].name, values[ds_index], value,
+                (value < min) ? "below" : "above",
+                (state == STATE_ERROR) ? "failure" : "warning",
+                (value < min) ? min : max);
     } else /* is not inverted */
     {
-      snprintf(buf, bufsize, ": Data source \"%s\" is currently "
-                             "%f. That is %s the %s threshold of %f.",
-               ds->ds[ds_index].name, values[ds_index],
-               (values[ds_index] < min) ? "below" : "above",
-               (state == STATE_ERROR) ? "failure" : "warning",
-               (values[ds_index] < min) ? min : max);
+      ssnprintf(buf, bufsize,
+                ": Data source \"%s\" is currently "
+                "%f. That is %s the %s threshold of %f.",
+                ds->ds[ds_index].name, values[ds_index],
+                (values[ds_index] < min) ? "below" : "above",
+                (state == STATE_ERROR) ? "failure" : "warning",
+                (values[ds_index] < min) ? min : max);
     }
   }
 
@@ -689,9 +692,9 @@ static int ut_missing(const value_list_t *vl,
   FORMAT_VL(identifier, sizeof(identifier), vl);
 
   NOTIFICATION_INIT_VL(&n, vl);
-  snprintf(n.message, sizeof(n.message),
-           "%s has not been updated for %.3f seconds.", identifier,
-           CDTIME_T_TO_DOUBLE(missing_time));
+  ssnprintf(n.message, sizeof(n.message),
+            "%s has not been updated for %.3f seconds.", identifier,
+            CDTIME_T_TO_DOUBLE(missing_time));
   n.time = now;
 
   plugin_dispatch_notification(&n);
index ce57942..8bbb92b 100644 (file)
@@ -987,6 +987,8 @@ static int __attribute__((warn_unused_result)) probe_cpu(void) {
     /* Ivy Bridge */
     case 0x3A: /* IVB */
     case 0x3E: /* IVB Xeon */
+    case 0x55: /* SKX,CLX Xeon */
+    case 0x6A: /* ICX Xeon */
       do_smi = true;
       do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
       do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
@@ -1042,6 +1044,8 @@ static int __attribute__((warn_unused_result)) probe_cpu(void) {
       break;
     case 0x2D: /* SNB Xeon */
     case 0x3E: /* IVB Xeon */
+    case 0x55: /* SKX,CLX Xeon */
+    case 0x6A: /* ICX Xeon */
       do_rapl = RAPL_PKG | RAPL_CORES | RAPL_DRAM;
       do_power_fields = TURBO_PLATFORM | PSTATES_PLATFORM;
       break;
@@ -1099,7 +1103,11 @@ static int __attribute__((format(printf, 1, 2)))
 parse_int_file(const char *fmt, ...) {
   va_list args;
   char path[PATH_MAX];
+  char buf[256];
   int len;
+  value_t v;
+  char *c;
+  FILE *fp;
 
   va_start(args, fmt);
   len = vsnprintf(path, sizeof(path), fmt, args);
@@ -1109,8 +1117,29 @@ parse_int_file(const char *fmt, ...) {
     return -1;
   }
 
-  value_t v;
-  if (parse_value_file(path, &v, DS_TYPE_DERIVE) != 0) {
+  fp = fopen(path, "r");
+  if (fp == NULL) {
+    ERROR("turbostat plugin: unable to open: '%s': %s", path, strerror(errno));
+    return -1;
+  }
+
+  if (fgets(buf, sizeof(buf), fp) == NULL) {
+    ERROR("turbostat plugin: unable to read: '%s': %s", path, strerror(errno));
+    fclose(fp);
+    return -1;
+  }
+  fclose(fp);
+
+  /* We only care about the first integer in the range */
+  c = strchr(buf, '-');
+  if (c != NULL)
+    *c = '\0';
+  c = strchr(buf, ',');
+  if (c != NULL)
+    *c = '\0';
+  strstripnewline(buf);
+
+  if (parse_value(buf, &v, DS_TYPE_DERIVE) != 0) {
     ERROR("turbostat plugin: Parsing \"%s\" failed.", path);
     return -1;
   }
@@ -1434,9 +1463,9 @@ static void free_all_buffers(void) {
   package_delta = NULL;
 }
 
-/**********************
- * Collectd functions *
- **********************/
+  /**********************
  * Collectd functions *
  **********************/
 
 #define DO_OR_GOTO_ERR(something)                                              \
   do {                                                                         \
index 69f59b0..6c08936 100644 (file)
@@ -242,6 +242,7 @@ spam_score              value:GAUGE:U:U
 spl                     value:GAUGE:U:U
 swap                    value:GAUGE:0:1099511627776
 swap_io                 value:DERIVE:0:U
+sysevent                value:GAUGE:0:1
 tcp_connections         value:GAUGE:0:4294967295
 tdp                     value:GAUGE:U:U
 temperature             value:GAUGE:U:U
index dd33ab3..0892bda 100644 (file)
@@ -96,7 +96,7 @@ static time_t uptime_get_sys(void) { /* {{{ */
   }
 
   result = (time_t)info.uptime;
-/* #endif KERNEL_LINUX */
+  /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKSTAT
   kstat_t *ksp;
@@ -136,7 +136,7 @@ static time_t uptime_get_sys(void) { /* {{{ */
   }
 
   result = time(NULL) - (time_t)knp->value.ui32;
-/* #endif HAVE_LIBKSTAT */
+  /* #endif HAVE_LIBKSTAT */
 
 #elif HAVE_SYS_SYSCTL_H
   struct timeval boottv = {0};
@@ -161,7 +161,7 @@ static time_t uptime_get_sys(void) { /* {{{ */
   }
 
   result = time(NULL) - boottv.tv_sec;
-/* #endif HAVE_SYS_SYSCTL_H */
+  /* #endif HAVE_SYS_SYSCTL_H */
 
 #elif HAVE_PERFSTAT
   int status;
index fc03ba2..768d488 100644 (file)
@@ -71,7 +71,7 @@ static int users_read(void) {
   endutxent();
 
   users_submit(users);
-/* #endif HAVE_GETUTXENT */
+  /* #endif HAVE_GETUTXENT */
 
 #elif HAVE_GETUTENT
   unsigned int users = 0;
@@ -89,7 +89,7 @@ static int users_read(void) {
   endutent();
 
   users_submit(users);
-/* #endif HAVE_GETUTENT */
+  /* #endif HAVE_GETUTENT */
 
 #elif HAVE_LIBSTATGRAB
   sg_user_stats *us;
@@ -109,7 +109,7 @@ static int users_read(void) {
 #else
                    us->num_entries);
 #endif
-/* #endif HAVE_LIBSTATGRAB */
+  /* #endif HAVE_LIBSTATGRAB */
 
 #else
 #error "No applicable input method."
index 713f032..edbf5c9 100644 (file)
  *   Sebastian 'tokkee' Harl <sh at tokkee.org>
  **/
 
+// clang-format off
+/*
+ * Explicit order is required or _FILE_OFFSET_BITS will have definition mismatches on Solaris
+ * See Github Issue #3193 for details
+ */
+#include "utils/common/common.h"
 #include "testing.h"
 #include "utils/cmds/cmds.h"
-#include "utils/common/common.h"
+// clang-format on
 
 static void error_cb(void *ud, cmd_status_t status, const char *format,
                      va_list ap) {
@@ -51,114 +57,201 @@ static struct {
 } parse_data[] = {
     /* Valid FLUSH commands. */
     {
-        "FLUSH", NULL, CMD_OK, CMD_FLUSH,
+        "FLUSH",
+        NULL,
+        CMD_OK,
+        CMD_FLUSH,
     },
     {
-        "FLUSH identifier=myhost/magic/MAGIC", NULL, CMD_OK, CMD_FLUSH,
+        "FLUSH identifier=myhost/magic/MAGIC",
+        NULL,
+        CMD_OK,
+        CMD_FLUSH,
     },
     {
-        "FLUSH identifier=magic/MAGIC", &default_host_opts, CMD_OK, CMD_FLUSH,
+        "FLUSH identifier=magic/MAGIC",
+        &default_host_opts,
+        CMD_OK,
+        CMD_FLUSH,
     },
     {
-        "FLUSH timeout=123 plugin=\"A\"", NULL, CMD_OK, CMD_FLUSH,
+        "FLUSH timeout=123 plugin=\"A\"",
+        NULL,
+        CMD_OK,
+        CMD_FLUSH,
     },
     /* Invalid FLUSH commands. */
     {
         /* Missing hostname; no default. */
-        "FLUSH identifier=magic/MAGIC", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "FLUSH identifier=magic/MAGIC",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
         /* Missing 'identifier' key. */
-        "FLUSH myhost/magic/MAGIC", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "FLUSH myhost/magic/MAGIC",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
         /* Invalid timeout. */
-        "FLUSH timeout=A", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "FLUSH timeout=A",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
         /* Invalid identifier. */
-        "FLUSH identifier=invalid", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "FLUSH identifier=invalid",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
         /* Invalid option. */
-        "FLUSH invalid=option", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "FLUSH invalid=option",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
 
     /* Valid GETVAL commands. */
     {
-        "GETVAL myhost/magic/MAGIC", NULL, CMD_OK, CMD_GETVAL,
+        "GETVAL myhost/magic/MAGIC",
+        NULL,
+        CMD_OK,
+        CMD_GETVAL,
     },
     {
-        "GETVAL magic/MAGIC", &default_host_opts, CMD_OK, CMD_GETVAL,
+        "GETVAL magic/MAGIC",
+        &default_host_opts,
+        CMD_OK,
+        CMD_GETVAL,
     },
 
     /* Invalid GETVAL commands. */
     {
-        "GETVAL magic/MAGIC", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "GETVAL magic/MAGIC",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
-        "GETVAL", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "GETVAL",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
-        "GETVAL invalid", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "GETVAL invalid",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
 
     /* Valid LISTVAL commands. */
     {
-        "LISTVAL", NULL, CMD_OK, CMD_LISTVAL,
+        "LISTVAL",
+        NULL,
+        CMD_OK,
+        CMD_LISTVAL,
     },
 
     /* Invalid LISTVAL commands. */
     {
-        "LISTVAL invalid", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "LISTVAL invalid",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
 
     /* Valid PUTVAL commands. */
     {
-        "PUTVAL magic/MAGIC N:42", &default_host_opts, CMD_OK, CMD_PUTVAL,
+        "PUTVAL magic/MAGIC N:42",
+        &default_host_opts,
+        CMD_OK,
+        CMD_PUTVAL,
     },
     {
-        "PUTVAL myhost/magic/MAGIC N:42", NULL, CMD_OK, CMD_PUTVAL,
+        "PUTVAL myhost/magic/MAGIC N:42",
+        NULL,
+        CMD_OK,
+        CMD_PUTVAL,
     },
     {
-        "PUTVAL myhost/magic/MAGIC 1234:42", NULL, CMD_OK, CMD_PUTVAL,
+        "PUTVAL myhost/magic/MAGIC 1234:42",
+        NULL,
+        CMD_OK,
+        CMD_PUTVAL,
     },
     {
-        "PUTVAL myhost/magic/MAGIC 1234:42 2345:23", NULL, CMD_OK, CMD_PUTVAL,
+        "PUTVAL myhost/magic/MAGIC 1234:42 2345:23",
+        NULL,
+        CMD_OK,
+        CMD_PUTVAL,
     },
     {
-        "PUTVAL myhost/magic/MAGIC interval=2 1234:42", NULL, CMD_OK,
+        "PUTVAL myhost/magic/MAGIC interval=2 1234:42",
+        NULL,
+        CMD_OK,
         CMD_PUTVAL,
     },
     {
-        "PUTVAL myhost/magic/MAGIC interval=2 1234:42 interval=5 2345:23", NULL,
-        CMD_OK, CMD_PUTVAL,
+        "PUTVAL myhost/magic/MAGIC interval=2 1234:42 interval=5 2345:23",
+        NULL,
+        CMD_OK,
+        CMD_PUTVAL,
     },
 
     /* Invalid PUTVAL commands. */
     {
-        "PUTVAL magic/MAGIC N:42", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "PUTVAL magic/MAGIC N:42",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
-        "PUTVAL", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "PUTVAL",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
-        "PUTVAL invalid N:42", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "PUTVAL invalid N:42",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
-        "PUTVAL myhost/magic/MAGIC A:42", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "PUTVAL myhost/magic/MAGIC A:42",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
-        "PUTVAL myhost/magic/MAGIC 1234:A", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "PUTVAL myhost/magic/MAGIC 1234:A",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
-        "PUTVAL myhost/magic/MAGIC", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "PUTVAL myhost/magic/MAGIC",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
-        "PUTVAL 1234:A", NULL, CMD_PARSE_ERROR, CMD_UNKNOWN,
+        "PUTVAL 1234:A",
+        NULL,
+        CMD_PARSE_ERROR,
+        CMD_UNKNOWN,
     },
     {
-        "PUTVAL myhost/magic/UNKNOWN 1234:42", NULL, CMD_PARSE_ERROR,
+        "PUTVAL myhost/magic/UNKNOWN 1234:42",
+        NULL,
+        CMD_PARSE_ERROR,
         CMD_UNKNOWN,
     },
     /*
@@ -173,10 +266,16 @@ static struct {
 
     /* Invalid commands. */
     {
-        "INVALID", NULL, CMD_UNKNOWN_COMMAND, CMD_UNKNOWN,
+        "INVALID",
+        NULL,
+        CMD_UNKNOWN_COMMAND,
+        CMD_UNKNOWN,
     },
     {
-        "INVALID interval=2", NULL, CMD_UNKNOWN_COMMAND, CMD_UNKNOWN,
+        "INVALID interval=2",
+        NULL,
+        CMD_UNKNOWN_COMMAND,
+        CMD_UNKNOWN,
     },
 };
 
@@ -196,13 +295,14 @@ DEF_TEST(parse) {
     memset(&cmd, 0, sizeof(cmd));
 
     status = cmd_parse(input, &cmd, parse_data[i].opts, &err);
-    snprintf(description, sizeof(description), "cmd_parse (\"%s\", opts=%p) = "
-                                               "%d (type=%d [%s]); want %d "
-                                               "(type=%d [%s])",
-             parse_data[i].input, parse_data[i].opts, status, cmd.type,
-             CMD_TO_STRING(cmd.type), parse_data[i].expected_status,
-             parse_data[i].expected_type,
-             CMD_TO_STRING(parse_data[i].expected_type));
+    ssnprintf(description, sizeof(description),
+              "cmd_parse (\"%s\", opts=%p) = "
+              "%d (type=%d [%s]); want %d "
+              "(type=%d [%s])",
+              parse_data[i].input, parse_data[i].opts, status, cmd.type,
+              CMD_TO_STRING(cmd.type), parse_data[i].expected_status,
+              parse_data[i].expected_type,
+              CMD_TO_STRING(parse_data[i].expected_type));
     result = (status == parse_data[i].expected_status) &&
              (cmd.type == parse_data[i].expected_type);
     LOG(result, description);
index d15f9b7..2cebc0d 100644 (file)
@@ -25,7 +25,7 @@
  *   Niki W. Waibel <niki.waibel@gmx.net>
  *   Sebastian Harl <sh at tokkee.org>
  *   Michał Mirosław <mirq-linux at rere.qmqm.pl>
-**/
+ **/
 
 #include "collectd.h"
 
@@ -89,6 +89,18 @@ char *sstrncpy(char *dest, const char *src, size_t n) {
   return dest;
 } /* char *sstrncpy */
 
+/* ssnprintf returns result from vsnprintf conistent with snprintf */
+int ssnprintf(char *str, size_t sz, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+
+  int ret = vsnprintf(str, sz, format, ap);
+
+  va_end(ap);
+
+  return ret;
+} /* int ssnprintf */
+
 char *ssnprintf_alloc(char const *format, ...) /* {{{ */
 {
   char static_buffer[1024] = "";
@@ -165,7 +177,7 @@ char *sstrerror(int errnum, char *buf, size_t buflen) {
 
     pthread_mutex_unlock(&strerror_r_lock);
   }
-/* #endif !HAVE_STRERROR_R */
+    /* #endif !HAVE_STRERROR_R */
 
 #elif STRERROR_R_CHAR_P
   {
@@ -175,17 +187,19 @@ char *sstrerror(int errnum, char *buf, size_t buflen) {
       if ((temp != NULL) && (temp != buf) && (temp[0] != '\0'))
         sstrncpy(buf, temp, buflen);
       else
-        sstrncpy(buf, "strerror_r did not return "
-                      "an error message",
+        sstrncpy(buf,
+                 "strerror_r did not return "
+                 "an error message",
                  buflen);
     }
   }
-/* #endif STRERROR_R_CHAR_P */
+    /* #endif STRERROR_R_CHAR_P */
 
 #else
   if (strerror_r(errnum, buf, buflen) != 0) {
-    snprintf(buf, buflen, "Error #%i; "
-                          "Additionally, strerror_r failed.",
+    snprintf(buf, buflen,
+             "Error #%i; "
+             "Additionally, strerror_r failed.",
              errnum);
   }
 #endif /* STRERROR_R_CHAR_P */
@@ -721,9 +735,8 @@ long long get_kstat_value(kstat_t *ksp, char *name) {
   else if (kn->data_type == KSTAT_DATA_UINT32)
     retval = (long long)kn->value.ui32;
   else if (kn->data_type == KSTAT_DATA_INT64)
-    retval =
-        (long long)kn->value.i64; /* According to ANSI C99 `long long' must hold
-                                     at least 64 bits */
+    retval = (long long)kn->value.i64; /* According to ANSI C99 `long long' must
+                                          hold at least 64 bits */
   else if (kn->data_type == KSTAT_DATA_UINT64)
     retval = (long long)kn->value.ui64; /* XXX: Might overflow! */
   else
@@ -752,8 +765,8 @@ unsigned long long htonll(unsigned long long n) {
 #endif /* HAVE_HTONLL */
 
 #if FP_LAYOUT_NEED_NOTHING
-/* Well, we need nothing.. */
-/* #endif FP_LAYOUT_NEED_NOTHING */
+  /* Well, we need nothing.. */
+  /* #endif FP_LAYOUT_NEED_NOTHING */
 
 #elif FP_LAYOUT_NEED_ENDIANFLIP || FP_LAYOUT_NEED_INTSWAP
 #if FP_LAYOUT_NEED_ENDIANFLIP
@@ -1250,7 +1263,7 @@ int walk_directory(const char *dir, dirwalk_callback_f callback,
   return 0;
 }
 
-ssize_t read_file_contents(const char *filename, char *buf, size_t bufsize) {
+ssize_t read_file_contents(const char *filename, void *buf, size_t bufsize) {
   FILE *fh;
   ssize_t ret;
 
@@ -1268,6 +1281,16 @@ ssize_t read_file_contents(const char *filename, char *buf, size_t bufsize) {
   return ret;
 }
 
+ssize_t read_text_file_contents(const char *filename, char *buf,
+                                size_t bufsize) {
+  ssize_t ret = read_file_contents(filename, buf, bufsize - 1);
+  if (ret < 0)
+    return ret;
+
+  buf[ret] = '\0';
+  return ret + 1;
+}
+
 counter_t counter_diff(counter_t old_value, counter_t new_value) {
   counter_t diff;
 
@@ -1439,13 +1462,13 @@ int service_name_to_port_number(const char *service_name) {
       service_number = (int)ntohs(sa->sin6_port);
     }
 
-    if ((service_number > 0) && (service_number <= 65535))
+    if (service_number > 0)
       break;
   }
 
   freeaddrinfo(ai_list);
 
-  if ((service_number > 0) && (service_number <= 65535))
+  if (service_number > 0)
     return service_number;
   return -1;
 } /* int service_name_to_port_number */
index addf06d..4e2eced 100644 (file)
@@ -23,7 +23,7 @@
  * Authors:
  *   Florian octo Forster <octo at collectd.org>
  *   Niki W. Waibel <niki.waibel@gmx.net>
-**/
+ **/
 
 #ifndef COMMON_H
 #define COMMON_H
@@ -66,6 +66,9 @@ typedef struct value_to_rate_state_s value_to_rate_state_t;
 
 char *sstrncpy(char *dest, const char *src, size_t n);
 
+__attribute__((format(printf, 3, 4))) int ssnprintf(char *str, size_t size,
+                                                    char const *format, ...);
+
 __attribute__((format(printf, 1, 2))) char *ssnprintf_alloc(char const *format,
                                                             ...);
 
@@ -353,7 +356,11 @@ typedef int (*dirwalk_callback_f)(const char *dirname, const char *filename,
 int walk_directory(const char *dir, dirwalk_callback_f callback,
                    void *user_data, int hidden);
 /* Returns the number of bytes read or negative on error. */
-ssize_t read_file_contents(char const *filename, char *buf, size_t bufsize);
+ssize_t read_file_contents(char const *filename, void *buf, size_t bufsize);
+/* Writes the contents of the file into the buffer with a trailing NUL.
+ * Returns the number of bytes written to the buffer or negative on error. */
+ssize_t read_text_file_contents(char const *filename, char *buf,
+                                size_t bufsize);
 
 counter_t counter_diff(counter_t old_value, counter_t new_value);
 
index 426082f..b8b3b4f 100644 (file)
  *   Florian octo Forster <octo at collectd.org>
  */
 
-#include "testing.h"
+// clang-format off
+/*
+ * Explicit order is required or _FILE_OFFSET_BITS will have definition mismatches on Solaris
+ * See Github Issue #3193 for details
+ */
 #include "utils/common/common.h"
+#include "testing.h"
+// clang-format on
 
 #if HAVE_KSTAT_H
 #include <kstat.h>
@@ -190,9 +196,9 @@ DEF_TEST(escape_slashes) {
   };
 
   for (size_t i = 0; i < STATIC_ARRAY_SIZE(cases); i++) {
-    char buffer[32];
+    char buffer[32] = {0};
 
-    strncpy(buffer, cases[i].str, sizeof(buffer));
+    strncpy(buffer, cases[i].str, sizeof(buffer) - 1);
     OK(escape_slashes(buffer, sizeof(buffer)) == 0);
     EXPECT_EQ_STR(cases[i].want, buffer);
   }
@@ -215,9 +221,9 @@ DEF_TEST(escape_string) {
   };
 
   for (size_t i = 0; i < STATIC_ARRAY_SIZE(cases); i++) {
-    char buffer[16];
+    char buffer[16] = {0};
 
-    strncpy(buffer, cases[i].str, sizeof(buffer));
+    strncpy(buffer, cases[i].str, sizeof(buffer) - 1);
     OK(escape_string(buffer, sizeof(buffer)) == 0);
     EXPECT_EQ_STR(cases[i].want, buffer);
   }
@@ -226,33 +232,33 @@ DEF_TEST(escape_string) {
 }
 
 DEF_TEST(strunescape) {
-  char buffer[16];
+  char buffer[32] = {0};
   int status;
 
-  strncpy(buffer, "foo\\tbar", sizeof(buffer));
+  strncpy(buffer, "foo\\tbar", sizeof(buffer) - 1);
   status = strunescape(buffer, sizeof(buffer));
   OK(status == 0);
   EXPECT_EQ_STR("foo\tbar", buffer);
 
-  strncpy(buffer, "\\tfoo\\r\\n", sizeof(buffer));
+  strncpy(buffer, "\\tfoo\\r\\n", sizeof(buffer) - 1);
   status = strunescape(buffer, sizeof(buffer));
   OK(status == 0);
   EXPECT_EQ_STR("\tfoo\r\n", buffer);
 
-  strncpy(buffer, "With \\\"quotes\\\"", sizeof(buffer));
+  strncpy(buffer, "With \\\"quotes\\\"", sizeof(buffer) - 1);
   status = strunescape(buffer, sizeof(buffer));
   OK(status == 0);
   EXPECT_EQ_STR("With \"quotes\"", buffer);
 
   /* Backslash before null byte */
-  strncpy(buffer, "\\tbackslash end\\", sizeof(buffer));
+  strncpy(buffer, "\\tbackslash end\\", sizeof(buffer) - 1);
   status = strunescape(buffer, sizeof(buffer));
   OK(status != 0);
   EXPECT_EQ_STR("\tbackslash end", buffer);
   return 0;
 
   /* Backslash at buffer end */
-  strncpy(buffer, "\\t3\\56", sizeof(buffer));
+  strncpy(buffer, "\\t3\\56", sizeof(buffer) - 1);
   status = strunescape(buffer, 4);
   OK(status != 0);
   OK(buffer[0] == '\t');
@@ -280,10 +286,15 @@ DEF_TEST(parse_values) {
 
   for (size_t i = 0; i < STATIC_ARRAY_SIZE(cases); i++) {
     data_source_t dsrc = {
-        .name = "value", .type = DS_TYPE_GAUGE, .min = 0.0, .max = NAN,
+        .name = "value",
+        .type = DS_TYPE_GAUGE,
+        .min = 0.0,
+        .max = NAN,
     };
     data_set_t ds = {
-        .type = "example", .ds_num = 1, .ds = &dsrc,
+        .type = "example",
+        .ds_num = 1,
+        .ds = &dsrc,
     };
 
     value_t v = {
@@ -344,7 +355,8 @@ DEF_TEST(value_to_rate) {
   for (size_t i = 0; i < STATIC_ARRAY_SIZE(cases); i++) {
     cdtime_t t0 = TIME_T_TO_CDTIME_T(cases[i].t0);
     value_to_rate_state_t state = {
-        .last_value = cases[i].v0, .last_time = t0,
+        .last_value = cases[i].v0,
+        .last_time = t0,
     };
     gauge_t got;
 
index 13ea687..b6dedbc 100644 (file)
@@ -254,7 +254,7 @@ int config_cores_parse(const oconfig_item_t *ci, core_groups_list_t *cgl) {
     } else {
       for (size_t j = 0; j < n && cg_idx < STATIC_ARRAY_SIZE(cgroups); j++) {
         char desc[DATA_MAX_NAME_LEN];
-        snprintf(desc, sizeof(desc), "%u", cores[j]);
+        ssnprintf(desc, sizeof(desc), "%u", cores[j]);
 
         cgroups[cg_idx].desc = strdup(desc);
         if (cgroups[cg_idx].desc == NULL) {
@@ -313,7 +313,7 @@ int config_cores_default(int num_cores, core_groups_list_t *cgl) {
 
   for (int i = 0; i < num_cores; i++) {
     char desc[DATA_MAX_NAME_LEN];
-    snprintf(desc, sizeof(desc), "%d", i);
+    ssnprintf(desc, sizeof(desc), "%d", i);
 
     cgl->cgroups[i].cores = calloc(1, sizeof(*(cgl->cgroups[i].cores)));
     if (cgl->cgroups[i].cores == NULL) {
index 392bd56..fa43fe5 100644 (file)
@@ -228,8 +228,8 @@ static int udb_result_submit(udb_result_t *r, /* {{{ */
       }
       tmp[sizeof(tmp) - 1] = '\0';
 
-      snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s",
-               r->instance_prefix, tmp);
+      ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s",
+                r->instance_prefix, tmp);
     }
   }
   vl.type_instance[sizeof(vl.type_instance) - 1] = '\0';
index 2ea919b..981828d 100644 (file)
 #if HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif
-#if HAVE_ARPA_NAMESER_H
-#include <arpa/nameser.h>
-#endif
-#if HAVE_ARPA_NAMESER_COMPAT_H
-#include <arpa/nameser_compat.h>
-#endif
 
 #if HAVE_NETDB_H
 #include <netdb.h>
@@ -472,7 +466,7 @@ static int handle_ipv6(struct ip6_hdr *ipv6, int len) {
 
   return 1; /* Success */
 } /* int handle_ipv6 */
-/* #endif HAVE_IPV6 */
+  /* #endif HAVE_IPV6 */
 
 #else  /* if !HAVE_IPV6 */
 static int handle_ipv6(__attribute__((unused)) void *pkg,
@@ -666,253 +660,184 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr,
 
 const char *qtype_str(int t) {
   static char buf[32];
+  // clang-format off
+  /*
+  Built (with minor cleanup) from glibc-2.29 by
+    cat resolv/arpa/nameser.h | grep "ns_t_" | \
+    perl -ne '/ns_t_(\S+)\ =\ (\d+)/; print "  case $2:\n    return \"".uc($1)."\";\n";'
+  */
+  // clang-format on
   switch (t) {
-#if (defined(__NAMESER)) && (__NAMESER >= 19991001)
-  case ns_t_a:
+  case 1:
     return "A";
-  case ns_t_ns:
+  case 2:
     return "NS";
-  case ns_t_md:
+  case 3:
     return "MD";
-  case ns_t_mf:
+  case 4:
     return "MF";
-  case ns_t_cname:
+  case 5:
     return "CNAME";
-  case ns_t_soa:
+  case 6:
     return "SOA";
-  case ns_t_mb:
+  case 7:
     return "MB";
-  case ns_t_mg:
+  case 8:
     return "MG";
-  case ns_t_mr:
+  case 9:
     return "MR";
-  case ns_t_null:
+  case 10:
     return "NULL";
-  case ns_t_wks:
+  case 11:
     return "WKS";
-  case ns_t_ptr:
+  case 12:
     return "PTR";
-  case ns_t_hinfo:
+  case 13:
     return "HINFO";
-  case ns_t_minfo:
+  case 14:
     return "MINFO";
-  case ns_t_mx:
+  case 15:
     return "MX";
-  case ns_t_txt:
+  case 16:
     return "TXT";
-  case ns_t_rp:
+  case 17:
     return "RP";
-  case ns_t_afsdb:
+  case 18:
     return "AFSDB";
-  case ns_t_x25:
+  case 19:
     return "X25";
-  case ns_t_isdn:
+  case 20:
     return "ISDN";
-  case ns_t_rt:
+  case 21:
     return "RT";
-  case ns_t_nsap:
+  case 22:
     return "NSAP";
-  case ns_t_nsap_ptr:
+  case 23:
     return "NSAP-PTR";
-  case ns_t_sig:
+  case 24:
     return "SIG";
-  case ns_t_key:
+  case 25:
     return "KEY";
-  case ns_t_px:
+  case 26:
     return "PX";
-  case ns_t_gpos:
+  case 27:
     return "GPOS";
-  case ns_t_aaaa:
+  case 28:
     return "AAAA";
-  case ns_t_loc:
+  case 29:
     return "LOC";
-  case ns_t_nxt:
+  case 30:
     return "NXT";
-  case ns_t_eid:
+  case 31:
     return "EID";
-  case ns_t_nimloc:
+  case 32:
     return "NIMLOC";
-  case ns_t_srv:
+  case 33:
     return "SRV";
-  case ns_t_atma:
+  case 34:
     return "ATMA";
-  case ns_t_naptr:
+  case 35:
     return "NAPTR";
-  case ns_t_opt:
-    return "OPT";
-#if __NAMESER >= 19991006
-  case ns_t_kx:
+  case 36:
     return "KX";
-  case ns_t_cert:
+  case 37:
     return "CERT";
-  case ns_t_a6:
+  case 38:
     return "A6";
-  case ns_t_dname:
+  case 39:
     return "DNAME";
-  case ns_t_sink:
+  case 40:
     return "SINK";
-  case ns_t_tsig:
-    return "TSIG";
-#endif
-#if __NAMESER >= 20090302
-  case ns_t_apl:
+  case 41:
+    return "OPT";
+  case 42:
     return "APL";
-  case ns_t_ds:
+  case 43:
     return "DS";
-  case ns_t_sshfp:
+  case 44:
     return "SSHFP";
-  case ns_t_ipseckey:
+  case 45:
     return "IPSECKEY";
-  case ns_t_rrsig:
+  case 46:
     return "RRSIG";
-  case ns_t_nsec:
+  case 47:
     return "NSEC";
-  case ns_t_dnskey:
+  case 48:
     return "DNSKEY";
-  case ns_t_dhcid:
+  case 49:
     return "DHCID";
-  case ns_t_nsec3:
+  case 50:
     return "NSEC3";
-  case ns_t_nsec3param:
+  case 51:
     return "NSEC3PARAM";
-  case ns_t_hip:
+  case 52:
+    return "TLSA";
+  case 53:
+    return "SMIMEA";
+  case 55:
     return "HIP";
-  case ns_t_spf:
+  case 56:
+    return "NINFO";
+  case 57:
+    return "RKEY";
+  case 58:
+    return "TALINK";
+  case 59:
+    return "CDS";
+  case 60:
+    return "CDNSKEY";
+  case 61:
+    return "OPENPGPKEY";
+  case 62:
+    return "CSYNC";
+  case 99:
     return "SPF";
-  case ns_t_ixfr:
+  case 100:
+    return "UINFO";
+  case 101:
+    return "UID";
+  case 102:
+    return "GID";
+  case 103:
+    return "UNSPEC";
+  case 104:
+    return "NID";
+  case 105:
+    return "L32";
+  case 106:
+    return "L64";
+  case 107:
+    return "LP";
+  case 108:
+    return "EUI48";
+  case 109:
+    return "EUI64";
+  case 249:
+    return "TKEY";
+  case 250:
+    return "TSIG";
+  case 251:
     return "IXFR";
-#endif
-  case ns_t_axfr:
+  case 252:
     return "AXFR";
-  case ns_t_mailb:
+  case 253:
     return "MAILB";
-  case ns_t_maila:
+  case 254:
     return "MAILA";
-  case ns_t_any:
+  case 255:
     return "ANY";
-#if __NAMESER >= 19991006
-  case ns_t_zxfr:
-    return "ZXFR";
-#endif
-#if __NAMESER >= 20090302
-  case ns_t_dlv:
+  case 256:
+    return "URI";
+  case 257:
+    return "CAA";
+  case 258:
+    return "AVC";
+  case 32768:
+    return "TA";
+  case 32769:
     return "DLV";
-#endif
-/* #endif __NAMESER >= 19991001 */
-#elif (defined(__BIND)) && (__BIND >= 19950621)
-  case T_A:
-    return "A"; /* 1 ... */
-  case T_NS:
-    return "NS";
-  case T_MD:
-    return "MD";
-  case T_MF:
-    return "MF";
-  case T_CNAME:
-    return "CNAME";
-  case T_SOA:
-    return "SOA";
-  case T_MB:
-    return "MB";
-  case T_MG:
-    return "MG";
-  case T_MR:
-    return "MR";
-  case T_NULL:
-    return "NULL";
-  case T_WKS:
-    return "WKS";
-  case T_PTR:
-    return "PTR";
-  case T_HINFO:
-    return "HINFO";
-  case T_MINFO:
-    return "MINFO";
-  case T_MX:
-    return "MX";
-  case T_TXT:
-    return "TXT";
-  case T_RP:
-    return "RP";
-  case T_AFSDB:
-    return "AFSDB";
-  case T_X25:
-    return "X25";
-  case T_ISDN:
-    return "ISDN";
-  case T_RT:
-    return "RT";
-  case T_NSAP:
-    return "NSAP";
-  case T_NSAP_PTR:
-    return "NSAP_PTR";
-  case T_SIG:
-    return "SIG";
-  case T_KEY:
-    return "KEY";
-  case T_PX:
-    return "PX";
-  case T_GPOS:
-    return "GPOS";
-  case T_AAAA:
-    return "AAAA";
-  case T_LOC:
-    return "LOC";
-  case T_NXT:
-    return "NXT";
-  case T_EID:
-    return "EID";
-  case T_NIMLOC:
-    return "NIMLOC";
-  case T_SRV:
-    return "SRV";
-  case T_ATMA:
-    return "ATMA";
-  case T_NAPTR:
-    return "NAPTR"; /* ... 35 */
-#if (__BIND >= 19960801)
-  case T_KX:
-    return "KX"; /* 36 ... */
-  case T_CERT:
-    return "CERT";
-  case T_A6:
-    return "A6";
-  case T_DNAME:
-    return "DNAME";
-  case T_SINK:
-    return "SINK";
-  case T_OPT:
-    return "OPT";
-  case T_APL:
-    return "APL";
-  case T_DS:
-    return "DS";
-  case T_SSHFP:
-    return "SSHFP";
-  case T_RRSIG:
-    return "RRSIG";
-  case T_NSEC:
-    return "NSEC";
-  case T_DNSKEY:
-    return "DNSKEY"; /* ... 48 */
-  case T_TKEY:
-    return "TKEY"; /* 249 */
-#endif /* __BIND >= 19960801 */
-  case T_TSIG:
-    return "TSIG"; /* 250 ... */
-  case T_IXFR:
-    return "IXFR";
-  case T_AXFR:
-    return "AXFR";
-  case T_MAILB:
-    return "MAILB";
-  case T_MAILA:
-    return "MAILA";
-  case T_ANY:
-    return "ANY"; /* ... 255 */
-#endif /* __BIND >= 19950621 */
   default:
-    snprintf(buf, sizeof(buf), "#%i", t);
+    ssnprintf(buf, sizeof(buf), "#%i", t);
     return buf;
   } /* switch (t) */
 }
@@ -931,74 +856,55 @@ const char *opcode_str(int o) {
   case 5:
     return "Update";
   default:
-    snprintf(buf, sizeof(buf), "Opcode%d", o);
+    ssnprintf(buf, sizeof(buf), "Opcode%d", o);
     return buf;
   }
 }
 
 const char *rcode_str(int rcode) {
   static char buf[32];
+  /* RFC2136 rcodes */
+  // clang-format off
+  /*
+  Built (with minor cleanup) from glibc-2.29 by
+    cat resolv/arpa/nameser.h | grep "ns_r_" | \
+    perl -ne '/ns_r_(\S+)\ =\ (\d+)/; print "  case $2:\n    return \"".uc($1)."\";\n";'
+
+  https://tools.ietf.org/html/rfc2671 assigns EDNS Extended RCODE "16" to "BADVERS"
+  https://tools.ietf.org/html/rfc2845 declares 0..15 as DNS RCODE and 16 is BADSIG.
+  */
+  // clang-format on
   switch (rcode) {
-#if (defined(__NAMESER)) && (__NAMESER >= 19991006)
-  case ns_r_noerror:
-    return "NOERROR";
-  case ns_r_formerr:
+  case 1:
     return "FORMERR";
-  case ns_r_servfail:
+  case 2:
     return "SERVFAIL";
-  case ns_r_nxdomain:
+  case 3:
     return "NXDOMAIN";
-  case ns_r_notimpl:
+  case 4:
     return "NOTIMPL";
-  case ns_r_refused:
+  case 5:
     return "REFUSED";
-  case ns_r_yxdomain:
+  case 6:
     return "YXDOMAIN";
-  case ns_r_yxrrset:
+  case 7:
     return "YXRRSET";
-  case ns_r_nxrrset:
+  case 8:
     return "NXRRSET";
-  case ns_r_notauth:
+  case 9:
     return "NOTAUTH";
-  case ns_r_notzone:
+  case 10:
     return "NOTZONE";
-  case ns_r_max:
+  case 11:
     return "MAX";
-  case ns_r_badsig:
+  case 16:
     return "BADSIG";
-  case ns_r_badkey:
+  case 17:
     return "BADKEY";
-  case ns_r_badtime:
+  case 18:
     return "BADTIME";
-/* #endif __NAMESER >= 19991006 */
-#elif (defined(__BIND)) && (__BIND >= 19950621)
-  case NOERROR:
-    return "NOERROR";
-  case FORMERR:
-    return "FORMERR";
-  case SERVFAIL:
-    return "SERVFAIL";
-  case NXDOMAIN:
-    return "NXDOMAIN";
-  case NOTIMP:
-    return "NOTIMP";
-  case REFUSED:
-    return "REFUSED";
-#if defined(YXDOMAIN) && defined(NXRRSET)
-  case YXDOMAIN:
-    return "YXDOMAIN";
-  case YXRRSET:
-    return "YXRRSET";
-  case NXRRSET:
-    return "NXRRSET";
-  case NOTAUTH:
-    return "NOTAUTH";
-  case NOTZONE:
-    return "NOTZONE";
-#endif /* RFC2136 rcodes */
-#endif /* __BIND >= 19950621 */
   default:
-    snprintf(buf, sizeof(buf), "RCode%i", rcode);
+    ssnprintf(buf, sizeof(buf), "RCode%i", rcode);
     return buf;
   }
 } /* const char *rcode_str (int rcode) */
index 9d9b75f..9cc49b6 100644 (file)
@@ -38,7 +38,6 @@
 
 #include "config.h"
 
-#include <arpa/nameser.h>
 #include <stdint.h>
 
 #if HAVE_PCAP_H
index 5e38ab3..7d9f7ab 100644 (file)
@@ -110,10 +110,10 @@ static void dpdk_helper_config_default(dpdk_helper_ctx_t *phc) {
 
   DPDK_HELPER_TRACE(phc->shm_name);
 
-  snprintf(phc->eal_config.coremask, DATA_MAX_NAME_LEN, "%s", "0xf");
-  snprintf(phc->eal_config.memory_channels, DATA_MAX_NAME_LEN, "%s", "1");
-  snprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN, "%s",
-           DPDK_DEFAULT_RTE_CONFIG);
+  ssnprintf(phc->eal_config.coremask, DATA_MAX_NAME_LEN, "%s", "0xf");
+  ssnprintf(phc->eal_config.memory_channels, DATA_MAX_NAME_LEN, "%s", "1");
+  ssnprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN, "%s",
+            DPDK_DEFAULT_RTE_CONFIG);
 }
 
 int dpdk_helper_eal_config_set(dpdk_helper_ctx_t *phc, dpdk_eal_config_t *ec) {
@@ -189,11 +189,11 @@ int dpdk_helper_eal_config_parse(dpdk_helper_ctx_t *phc, oconfig_item_t *ci) {
       status = cf_util_get_string_buffer(child, prefix, sizeof(prefix));
       if (status == 0) {
 #if RTE_VERSION <= RTE_VERSION_NUM(18, 5, 0, 0)
-        snprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN,
-                 "/var/run/.%s_config", prefix);
+        ssnprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN,
+                  "/var/run/.%s_config", prefix);
 #else
-        snprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN,
-                 "/var/run/dpdk/%s/config", prefix);
+        ssnprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN,
+                  "/var/run/dpdk/%s/config", prefix);
 #endif
         DEBUG("dpdk_common: EAL:File prefix %s", phc->eal_config.file_prefix);
       }
@@ -304,8 +304,8 @@ int dpdk_helper_init(const char *name, size_t data_size,
   DPDK_HELPER_TRACE(name);
 
   /* Allocate dpdk_helper_ctx_t and
-  * initialize a POSIX SHared Memory (SHM) object.
-  */
+   * initialize a POSIX SHared Memory (SHM) object.
+   */
   int err = dpdk_shm_init(name, shm_size, (void **)&phc);
   if (err != 0) {
     return -errno;
@@ -704,7 +704,8 @@ static void dpdk_helper_check_pipe(dpdk_helper_ctx_t *phc) {
 
   /* non blocking check on helper logging pipe */
   struct pollfd fds = {
-      .fd = phc->pipes[0], .events = POLLIN,
+      .fd = phc->pipes[0],
+      .events = POLLIN,
   };
   int data_avail = poll(&fds, 1, 0);
   DEBUG("%s:dpdk_helper_check_pipe: poll data_avail=%d", phc->shm_name,
index 2c14d01..e01317b 100644 (file)
@@ -154,7 +154,7 @@ DEF_TEST(metric_name) {
     };
 
     char want[1024];
-    snprintf(want, sizeof(want), "%s 42 1480063672\r\n", cases[i].want_name);
+    ssnprintf(want, sizeof(want), "%s 42 1480063672\r\n", cases[i].want_name);
 
     if (cases[i].plugin_instance != NULL)
       sstrncpy(vl.plugin_instance, cases[i].plugin_instance,
index b82f21d..ac3729a 100644 (file)
@@ -578,12 +578,11 @@ static int format_alert(yajl_gen g, notification_t const *n) /* {{{ */
   }
 
   JSON_ADD(g, "severity");
-  JSON_ADD(g,
-           (n->severity == NOTIF_FAILURE)
-               ? "FAILURE"
-               : (n->severity == NOTIF_WARNING)
-                     ? "WARNING"
-                     : (n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN");
+  JSON_ADD(g, (n->severity == NOTIF_FAILURE)
+                  ? "FAILURE"
+                  : (n->severity == NOTIF_WARNING)
+                        ? "WARNING"
+                        : (n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN");
 
   JSON_ADD(g, "service");
   JSON_ADD(g, "collectd");
index d041604..30c89bb 100644 (file)
@@ -131,7 +131,8 @@ static int test_string(void *ctx, unsigned char const *value,
 
 static int expect_json_labels(char *json, label_t *labels, size_t labels_num) {
   yajl_callbacks funcs = {
-      .yajl_string = test_string, .yajl_map_key = test_map_key,
+      .yajl_string = test_string,
+      .yajl_map_key = test_map_key,
   };
 
   test_case_t c = {labels, labels_num, NULL};
index 80b85ae..ccb1c77 100644 (file)
@@ -144,16 +144,16 @@ static int format_typed_value(yajl_gen gen, int ds_type, value_t v,
   }
   case DS_TYPE_DERIVE: {
     derive_t diff = v.derive - (derive_t)start_value;
-    snprintf(integer, sizeof(integer), "%" PRIi64, diff);
+    ssnprintf(integer, sizeof(integer), "%" PRIi64, diff);
     break;
   }
   case DS_TYPE_COUNTER: {
     counter_t diff = counter_diff((counter_t)start_value, v.counter);
-    snprintf(integer, sizeof(integer), "%llu", diff);
+    ssnprintf(integer, sizeof(integer), "%llu", diff);
     break;
   }
   case DS_TYPE_ABSOLUTE: {
-    snprintf(integer, sizeof(integer), "%" PRIu64, v.absolute);
+    ssnprintf(integer, sizeof(integer), "%" PRIu64, v.absolute);
     break;
   }
   default: {
@@ -177,7 +177,7 @@ static int format_typed_value(yajl_gen gen, int ds_type, value_t v,
  *   "CUMULATIVE",
  *   "GAUGE"
  * )
-*/
+ */
 static int format_metric_kind(yajl_gen gen, int ds_type) {
   switch (ds_type) {
   case DS_TYPE_GAUGE:
@@ -198,7 +198,7 @@ static int format_metric_kind(yajl_gen gen, int ds_type) {
  *   "DOUBLE",
  *   "INT64"
  * )
-*/
+ */
 static int format_value_type(yajl_gen gen, int ds_type) {
   return json_string(gen, (ds_type == DS_TYPE_GAUGE) ? "DOUBLE" : "INT64");
 }
@@ -210,10 +210,10 @@ static int metric_type(char *buffer, size_t buffer_size, data_set_t const *ds,
 
 #define GCM_PREFIX "custom.googleapis.com/collectd/"
   if ((ds_index != 0) || strcmp("value", ds_name) != 0) {
-    snprintf(buffer, buffer_size, GCM_PREFIX "%s/%s_%s", vl->plugin, vl->type,
-             ds_name);
+    ssnprintf(buffer, buffer_size, GCM_PREFIX "%s/%s_%s", vl->plugin, vl->type,
+              ds_name);
   } else {
-    snprintf(buffer, buffer_size, GCM_PREFIX "%s/%s", vl->plugin, vl->type);
+    ssnprintf(buffer, buffer_size, GCM_PREFIX "%s/%s", vl->plugin, vl->type);
   }
 
   char const *whitelist = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -280,8 +280,8 @@ static int read_cumulative_state(data_set_t const *ds, value_list_t const *vl,
   }
 
   char start_value_key[DATA_MAX_NAME_LEN];
-  snprintf(start_value_key, sizeof(start_value_key),
-           "stackdriver:start_value[%d]", ds_index);
+  ssnprintf(start_value_key, sizeof(start_value_key),
+            "stackdriver:start_value[%d]", ds_index);
 
   int status =
       uc_meta_data_get_signed_int(vl, start_value_key, ret_start_value);
index d4935a3..0a4f268 100644 (file)
@@ -27,7 +27,9 @@
 
 DEF_TEST(sd_format_metric_descriptor) {
   value_list_t vl = {
-      .host = "example.com", .plugin = "unit-test", .type = "example",
+      .host = "example.com",
+      .plugin = "unit-test",
+      .type = "example",
   };
   char got[1024];
 
@@ -36,7 +38,10 @@ DEF_TEST(sd_format_metric_descriptor) {
       .ds_num = 1,
       .ds =
           &(data_source_t){
-              .name = "value", .type = DS_TYPE_GAUGE, .min = NAN, .max = NAN,
+              .name = "value",
+              .type = DS_TYPE_GAUGE,
+              .min = NAN,
+              .max = NAN,
           },
   };
   EXPECT_EQ_INT(
index 8092765..48aacd9 100644 (file)
@@ -227,8 +227,8 @@ char *gce_scope(char const *email) /* {{{ */
 {
   char url[1024];
 
-  snprintf(url, sizeof(url), GCE_SCOPE_URL_FORMAT,
-           (email != NULL) ? email : GCE_DEFAULT_SERVICE_ACCOUNT);
+  ssnprintf(url, sizeof(url), GCE_SCOPE_URL_FORMAT,
+            (email != NULL) ? email : GCE_DEFAULT_SERVICE_ACCOUNT);
 
   return read_url(url);
 } /* }}} char *gce_scope */
@@ -252,7 +252,7 @@ int gce_access_token(char const *email, char *buffer,
     return 0;
   }
 
-  snprintf(url, sizeof(url), GCE_TOKEN_URL_FORMAT, email);
+  ssnprintf(url, sizeof(url), GCE_TOKEN_URL_FORMAT, email);
   json = read_url(url);
   if (json == NULL) {
     pthread_mutex_unlock(&token_lock);
index 12ff2ca..e32c97b 100644 (file)
@@ -56,22 +56,22 @@ struct latency_counter_s {
 };
 
 /*
-* Histogram represents the distribution of data, it has a list of "bins".
-* Each bin represents an interval and has a count (frequency) of
-* number of values fall within its interval.
-*
-* Histogram's range is determined by the number of bins and the bin width,
-* There are 1000 bins and all bins have the same width of default 1 millisecond.
-* When a value above this range is added, Histogram's range is increased by
-* increasing the bin width (note that number of bins remains always at 1000).
-* This operation of increasing bin width is little expensive as each bin need
-* to be visited to update its count. To reduce frequent change of bin width,
-* new bin width will be the next nearest power of 2. Example: 2, 4, 8, 16, 32,
-* 64, 128, 256, 512, 1024, 2048, 5086, ...
-*
-* So, if the required bin width is 300, then new bin width will be 512 as it is
-* the next nearest power of 2.
-*/
+ * Histogram represents the distribution of data, it has a list of "bins".
+ * Each bin represents an interval and has a count (frequency) of
+ * number of values fall within its interval.
+ *
+ * Histogram's range is determined by the number of bins and the bin width,
+ * There are 1000 bins and all bins have the same width of default 1
+ * millisecond. When a value above this range is added, Histogram's range is
+ * increased by increasing the bin width (note that number of bins remains
+ * always at 1000). This operation of increasing bin width is little expensive
+ * as each bin need to be visited to update its count. To reduce frequent change
+ * of bin width, new bin width will be the next nearest power of 2. Example: 2,
+ * 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 5086, ...
+ *
+ * So, if the required bin width is 300, then new bin width will be 512 as it is
+ * the next nearest power of 2.
+ */
 static void change_bin_width(latency_counter_t *lc, cdtime_t latency) /* {{{ */
 {
   /* This function is called because the new value is above histogram's range.
index 9d878da..6c2c8ae 100644 (file)
@@ -24,6 +24,9 @@
  *   Florian Forster <ff at octo.it>
  **/
 
+#ifndef UTILS_LATENCY_LATENCY_H
+#define UTILS_LATENCY_LATENCY_H 1
+
 #include "collectd.h"
 
 #include "utils_time.h"
@@ -61,3 +64,5 @@ cdtime_t latency_counter_get_percentile(latency_counter_t *lc, double percent);
  */
 double latency_counter_get_rate(const latency_counter_t *lc, cdtime_t lower,
                                 cdtime_t upper, const cdtime_t now);
+
+#endif /* UTILS_LATENCY_LATENCY_H */
index a5ae471..7d614e7 100644 (file)
@@ -124,7 +124,8 @@ int latency_config(latency_config_t *conf, oconfig_item_t *ci) {
 
 int latency_config_copy(latency_config_t *dst, const latency_config_t src) {
   *dst = (latency_config_t){
-      .percentile_num = src.percentile_num, .buckets_num = src.buckets_num,
+      .percentile_num = src.percentile_num,
+      .buckets_num = src.buckets_num,
   };
 
   dst->percentile = calloc(dst->percentile_num, sizeof(*dst->percentile));
index 1325017..8954463 100644 (file)
@@ -159,58 +159,75 @@ DEF_TEST(get_rate) {
   } cases[] = {
       {
           // bucket 6 is zero
-          DOUBLE_TO_CDTIME_T_STATIC(0.750), DOUBLE_TO_CDTIME_T_STATIC(0.875),
+          DOUBLE_TO_CDTIME_T_STATIC(0.750),
+          DOUBLE_TO_CDTIME_T_STATIC(0.875),
           0.00,
       },
       {
           // bucket 7 contains the t=1 update
-          DOUBLE_TO_CDTIME_T_STATIC(0.875), DOUBLE_TO_CDTIME_T_STATIC(1.000),
+          DOUBLE_TO_CDTIME_T_STATIC(0.875),
+          DOUBLE_TO_CDTIME_T_STATIC(1.000),
           1.00,
       },
       {
           // range: bucket 7 - bucket 15; contains the t=1 and t=2 updates
-          DOUBLE_TO_CDTIME_T_STATIC(0.875), DOUBLE_TO_CDTIME_T_STATIC(2.000),
+          DOUBLE_TO_CDTIME_T_STATIC(0.875),
+          DOUBLE_TO_CDTIME_T_STATIC(2.000),
           2.00,
       },
       {
           // lower bucket is only partially applied
           DOUBLE_TO_CDTIME_T_STATIC(0.875 + (0.125 / 4)),
-          DOUBLE_TO_CDTIME_T_STATIC(2.000), 1.75,
+          DOUBLE_TO_CDTIME_T_STATIC(2.000),
+          1.75,
       },
       {
           // upper bucket is only partially applied
           DOUBLE_TO_CDTIME_T_STATIC(0.875),
-          DOUBLE_TO_CDTIME_T_STATIC(2.000 - (0.125 / 4)), 1.75,
+          DOUBLE_TO_CDTIME_T_STATIC(2.000 - (0.125 / 4)),
+          1.75,
       },
       {
           // both buckets are only partially applied
           DOUBLE_TO_CDTIME_T_STATIC(0.875 + (0.125 / 4)),
-          DOUBLE_TO_CDTIME_T_STATIC(2.000 - (0.125 / 4)), 1.50,
+          DOUBLE_TO_CDTIME_T_STATIC(2.000 - (0.125 / 4)),
+          1.50,
       },
       {
           // lower bound is unspecified
-          0, DOUBLE_TO_CDTIME_T_STATIC(2.000), 2.00,
+          0,
+          DOUBLE_TO_CDTIME_T_STATIC(2.000),
+          2.00,
       },
       {
           // upper bound is unspecified
-          DOUBLE_TO_CDTIME_T_STATIC(125.000 - 0.125), 0, 1.00,
+          DOUBLE_TO_CDTIME_T_STATIC(125.000 - 0.125),
+          0,
+          1.00,
       },
       {
           // overflow test: upper >> longest latency
-          DOUBLE_TO_CDTIME_T_STATIC(1.000), DOUBLE_TO_CDTIME_T_STATIC(999999),
+          DOUBLE_TO_CDTIME_T_STATIC(1.000),
+          DOUBLE_TO_CDTIME_T_STATIC(999999),
           124.00,
       },
       {
           // overflow test: lower > longest latency
-          DOUBLE_TO_CDTIME_T_STATIC(130), 0, 0.00,
+          DOUBLE_TO_CDTIME_T_STATIC(130),
+          0,
+          0.00,
       },
       {
           // lower > upper => error
-          DOUBLE_TO_CDTIME_T_STATIC(10), DOUBLE_TO_CDTIME_T_STATIC(9), NAN,
+          DOUBLE_TO_CDTIME_T_STATIC(10),
+          DOUBLE_TO_CDTIME_T_STATIC(9),
+          NAN,
       },
       {
           // lower == upper => zero
-          DOUBLE_TO_CDTIME_T_STATIC(9), DOUBLE_TO_CDTIME_T_STATIC(9), 0.00,
+          DOUBLE_TO_CDTIME_T_STATIC(9),
+          DOUBLE_TO_CDTIME_T_STATIC(9),
+          0.00,
       },
   };
 
index 319c624..1d362e1 100644 (file)
@@ -18,7 +18,7 @@
  *
  * Author:
  *   Niki W. Waibel <niki.waibel@gmx.net>
-**/
+ **/
 
 #if HAVE_CONFIG_H
 #include "config.h"
@@ -250,14 +250,14 @@ static void uuidcache_init(void) {
 
       if (isdigit((int)s[-1])) {
         /*
-        * Note: this is a heuristic only - there is no reason
-        * why these devices should live in /dev.
-        * Perhaps this directory should be specifiable by option.
-        * One might for example have /devlabel with links to /dev
-        * for the devices that may be accessed in this way.
-        * (This is useful, if the cdrom on /dev/hdc must not
-        * be accessed.)
-        */
+         * Note: this is a heuristic only - there is no reason
+         * why these devices should live in /dev.
+         * Perhaps this directory should be specifiable by option.
+         * One might for example have /devlabel with links to /dev
+         * for the devices that may be accessed in this way.
+         * (This is useful, if the cdrom on /dev/hdc must not
+         * be accessed.)
+         */
         snprintf(device, sizeof(device), "%s/%s", DEVLABELDIR, ptname);
         if (!get_label_uuid(device, &label, uuid)) {
           uuidcache_addentry(sstrdup(device), label, uuid);
@@ -522,7 +522,7 @@ static cu_mount_t *cu_mount_gen_getmntent(void) {
 
 #elif HAVE_SEQ_GETMNTENT
 #warn "This version of `getmntent' hat not yet been implemented!"
-/* #endif HAVE_SEQ_GETMNTENT */
+  /* #endif HAVE_SEQ_GETMNTENT */
 
 #elif HAVE_GETMNTENT_R
 static cu_mount_t *cu_mount_getmntent(void) {
index 5bae546..05adcc3 100644 (file)
@@ -18,7 +18,7 @@
  *
  * Author:
  *   Niki W. Waibel <niki.waibel@gmx.net>
-**/
+ **/
 
 /* See below for instructions how to use the public functions. */
 
index 4b31056..a7ae75d 100644 (file)
@@ -184,9 +184,9 @@ static int get_claim(oauth_t *auth, char *buffer, size_t buffer_size) /* {{{ */
 
   /* create the claim set */
   status =
-      snprintf(claim, sizeof(claim), OAUTH_CLAIM_FORMAT, auth->iss, auth->scope,
-               auth->aud, (unsigned long)CDTIME_T_TO_TIME_T(exp),
-               (unsigned long)CDTIME_T_TO_TIME_T(iat));
+      ssnprintf(claim, sizeof(claim), OAUTH_CLAIM_FORMAT, auth->iss,
+                auth->scope, auth->aud, (unsigned long)CDTIME_T_TO_TIME_T(exp),
+                (unsigned long)CDTIME_T_TO_TIME_T(iat));
   if (status < 1)
     return -1;
   else if ((size_t)status >= sizeof(claim))
@@ -209,7 +209,7 @@ static int get_signature(char *buffer, size_t buffer_size, /* {{{ */
   int status;
 
   /* Make the string to sign */
-  payload_len = snprintf(payload, sizeof(payload), "%s.%s", header, claim);
+  payload_len = ssnprintf(payload, sizeof(payload), "%s.%s", header, claim);
   if (payload_len < 1) {
     return -1;
   } else if (payload_len >= sizeof(payload)) {
@@ -277,7 +277,7 @@ static int get_assertion(oauth_t *auth, char *buffer,
   if (status != 0)
     return -1;
 
-  status = snprintf(buffer, buffer_size, "%s.%s.%s", header, claim, signature);
+  status = ssnprintf(buffer, buffer_size, "%s.%s.%s", header, claim, signature);
   if (status < 1)
     return -1;
   else if ((size_t)status >= buffer_size)
@@ -350,8 +350,8 @@ static int new_token(oauth_t *auth) /* {{{ */
     return -1;
   }
 
-  snprintf(post_data, sizeof(post_data), "grant_type=%s&assertion=%s",
-           OAUTH_GRANT_TYPE, assertion);
+  ssnprintf(post_data, sizeof(post_data), "grant_type=%s&assertion=%s",
+            OAUTH_GRANT_TYPE, assertion);
 
   curl = curl_easy_init();
   if (curl == NULL) {
@@ -531,7 +531,8 @@ oauth_google_t oauth_create_google_json(char const *buffer, char const *scope) {
   }
 
   oauth_google_t ret = {
-      .project_id = strdup(project_id), .oauth = oauth,
+      .project_id = strdup(project_id),
+      .oauth = oauth,
   };
 
   yajl_tree_free(root);
@@ -589,8 +590,8 @@ oauth_google_t oauth_create_google_default(char const *scope) {
   char const *home;
   if ((home = getenv("HOME")) != NULL) {
     char path[PATH_MAX];
-    snprintf(path, sizeof(path),
-             "%s/.config/gcloud/application_default_credentials.json", home);
+    ssnprintf(path, sizeof(path),
+              "%s/.config/gcloud/application_default_credentials.json", home);
 
     oauth_google_t ret = oauth_create_google_file(path, scope);
     if (ret.oauth != NULL) {
index aa6e99a..36f2125 100644 (file)
@@ -35,21 +35,29 @@ struct {
 } cases[] = {
     {
         "{\"access_token\":\"MaeC6kaePhie1ree\",\"expires_in\":3600}",
-        /* status = */ 0, "MaeC6kaePhie1ree", TIME_T_TO_CDTIME_T_STATIC(3600),
+        /* status = */ 0,
+        "MaeC6kaePhie1ree",
+        TIME_T_TO_CDTIME_T_STATIC(3600),
     },
     {
         "{\"token_type\":\"Bearer\",\"expires_in\":1800,\"access_token\":"
         "\"aeThiebee2gushuY\"}",
-        /* status = */ 0, "aeThiebee2gushuY", TIME_T_TO_CDTIME_T_STATIC(1800),
+        /* status = */ 0,
+        "aeThiebee2gushuY",
+        TIME_T_TO_CDTIME_T_STATIC(1800),
     },
     {
         "{\"ignored_key\":\"uaph5aewaeghi1Ge\",\"expires_in\":3600}",
-        /* status = */ -1, NULL, 0,
+        /* status = */ -1,
+        NULL,
+        0,
     },
     {
         /* expires_in missing */
         "{\"access_token\":\"shaephohbie9Ahch\"}",
-        /* status = */ -1, NULL, 0,
+        /* status = */ -1,
+        NULL,
+        0,
     },
 };
 
index 46c2c26..52a590b 100644 (file)
@@ -785,7 +785,9 @@ static void *ovs_poll_worker(void *arg) {
   ovs_db_t *pdb = (ovs_db_t *)arg; /* pointer to OVS DB */
   ovs_json_reader_t *jreader = NULL;
   struct pollfd poll_fd = {
-      .fd = pdb->sock, .events = POLLIN | POLLPRI, .revents = 0,
+      .fd = pdb->sock,
+      .events = POLLIN | POLLPRI,
+      .revents = 0,
   };
 
   /* create JSON reader instance */
@@ -1117,7 +1119,7 @@ int ovs_db_send_request(ovs_db_t *pdb, const char *method, const char *params,
   /* generate id field */
   OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, "id");
   uid = ovs_uid_generate();
-  snprintf(uid_buff, sizeof(uid_buff), "%" PRIX64, uid);
+  ssnprintf(uid_buff, sizeof(uid_buff), "%" PRIX64, uid);
   OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, uid_buff);
 
   OVS_YAJL_CALL(yajl_gen_map_close, jgen);
@@ -1203,7 +1205,7 @@ int ovs_db_table_cb_register(ovs_db_t *pdb, const char *tb_name,
     OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, OVS_DB_DEFAULT_DB_NAME);
 
     /* uid string <json-value> */
-    snprintf(uid_str, sizeof(uid_str), "%" PRIX64, new_cb->uid);
+    ssnprintf(uid_str, sizeof(uid_str), "%" PRIX64, new_cb->uid);
     OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, uid_str);
 
     /* <monitor-requests> */
index 336a996..fb30172 100644 (file)
@@ -140,7 +140,7 @@ int pids_list_contains_pid(pids_list_t *list, const pid_t pid) {
  * RETURN VALUE
  *   On success, the number of read bytes (includes stripped \n).
  *   -1 on file open error
-*/
+ */
 static int read_proc_name(const char *procfs_path,
                           const struct dirent *pid_entry, char *name,
                           const size_t out_size) {
index 8b19497..9170398 100644 (file)
@@ -27,6 +27,9 @@
  *   Michał Aleksiński <michalx.aleksinski@intel.com>
  **/
 
+#ifndef UTILS_PROC_PIDS_PROC_PIDS_H
+#define UTILS_PROC_PIDS_PROC_PIDS_H 1
+
 #include <dirent.h>
 #include <sys/types.h>
 
@@ -224,3 +227,5 @@ int proc_pids_update(const char *procfs_path, proc_pids_t *proc_pids[],
  *   0 on success. -1 on error.
  */
 int proc_pids_free(proc_pids_t *proc_pids[], size_t proc_pids_num);
+
+#endif /* UTILS_PROC_PIDS_PROC_PIDS_H */
index 06b8d39..42d17f4 100644 (file)
@@ -1,5 +1,11 @@
-#include "testing.h"
+// clang-format off
+/*
+ * Explicit order is required or _FILE_OFFSET_BITS will have definition mismatches on Solaris
+ * See Github Issue #3193 for details
+ */
 #include "utils/proc_pids/proc_pids.c" /* sic */
+#include "testing.h"
+// clang-format on
 #include <sys/stat.h>
 
 /***************************************************************************
index ef01234..f543e11 100644 (file)
@@ -208,8 +208,8 @@ static int rra_get(char ***ret, const value_list_t *vl, /* {{{ */
       if (rra_num >= rra_max)
         break;
 
-      status = snprintf(buffer, sizeof(buffer), "RRA:%s:%.10f:%u:%u",
-                        rra_types[j], cfg->xff, cdp_len, cdp_num);
+      status = ssnprintf(buffer, sizeof(buffer), "RRA:%s:%.10f:%u:%u",
+                         rra_types[j], cfg->xff, cdp_len, cdp_num);
 
       if ((status < 0) || ((size_t)status >= sizeof(buffer))) {
         P_ERROR("rra_get: Buffer would have been truncated.");
@@ -278,14 +278,14 @@ static int ds_get(char ***ret, /* {{{ */
     if (isnan(d->min)) {
       sstrncpy(min, "U", sizeof(min));
     } else
-      snprintf(min, sizeof(min), "%f", d->min);
+      ssnprintf(min, sizeof(min), "%f", d->min);
 
     if (isnan(d->max)) {
       sstrncpy(max, "U", sizeof(max));
     } else
-      snprintf(max, sizeof(max), "%f", d->max);
+      ssnprintf(max, sizeof(max), "%f", d->max);
 
-    status = snprintf(
+    status = ssnprintf(
         buffer, sizeof(buffer), "DS:%s:%s:%i:%s:%s", d->name, type,
         (cfg->heartbeat > 0) ? cfg->heartbeat
                              : (int)CDTIME_T_TO_TIME_T(2 * vl->interval),
@@ -343,7 +343,7 @@ static int srrd_create(const char *filename, /* {{{ */
 
   return status;
 } /* }}} int srrd_create */
-/* #endif HAVE_THREADSAFE_LIBRRD */
+  /* #endif HAVE_THREADSAFE_LIBRRD */
 
 #else  /* !HAVE_THREADSAFE_LIBRRD */
 static int srrd_create(const char *filename, /* {{{ */
@@ -367,8 +367,8 @@ static int srrd_create(const char *filename, /* {{{ */
   if (last_up == 0)
     last_up = time(NULL) - 10;
 
-  snprintf(pdp_step_str, sizeof(pdp_step_str), "%lu", pdp_step);
-  snprintf(last_up_str, sizeof(last_up_str), "%lu", (unsigned long)last_up);
+  ssnprintf(pdp_step_str, sizeof(pdp_step_str), "%lu", pdp_step);
+  ssnprintf(last_up_str, sizeof(last_up_str), "%lu", (unsigned long)last_up);
 
   new_argv[0] = "create";
   new_argv[1] = (void *)filename;
@@ -496,7 +496,7 @@ static void *srrd_create_thread(void *targs) /* {{{ */
     return 0;
   }
 
-  snprintf(tmpfile, sizeof(tmpfile), "%s.async", args->filename);
+  ssnprintf(tmpfile, sizeof(tmpfile), "%s.async", args->filename);
 
   status = srrd_create(tmpfile, args->pdp_step, args->last_up, args->argc,
                        (void *)args->argv);
index b020c06..348f93f 100644 (file)
@@ -188,7 +188,8 @@ static int get_family_id(ts_t *ts) {
 
   struct genlmsghdr *genh = mnl_nlmsg_put_extra_header(nlh, sizeof(*genh));
   *genh = (struct genlmsghdr){
-      .cmd = CTRL_CMD_GETFAMILY, .version = 0x01,
+      .cmd = CTRL_CMD_GETFAMILY,
+      .version = 0x01,
   };
 
   mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, TASKSTATS_GENL_NAME);
index 0217a7e..771c241 100644 (file)
@@ -33,6 +33,9 @@
  *   regular expressions.
  */
 
+#ifndef UTILS_TAIL_MATCH_H
+#define UTILS_TAIL_MATCH_H 1
+
 #include "utils/latency/latency_config.h"
 #include "utils/match/match.h"
 
@@ -131,5 +134,7 @@ int tail_match_add_match_simple(cu_tail_match_t *obj, const char *regex,
  *
  * RETURN VALUE
  *   Zero on success, nonzero on failure.
-*/
+ */
 int tail_match_read(cu_tail_match_t *obj);
+
+#endif /* UTILS_TAIL_MATCH_H */
index 60d09b5..a5fba03 100644 (file)
@@ -29,7 +29,9 @@
 #include "plugin.h"
 #include "utils/common/common.h"
 
-#if HAVE_SYS_SYSCTL_H
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME) ||                \
+    defined(__OpenBSD__)
+/* Implies have BSD variant */
 #include <sys/sysctl.h>
 #endif
 
index b4ae438..f4c70af 100644 (file)
@@ -107,8 +107,8 @@ static int varnish_submit(const char *plugin_instance, /* {{{ */
 
   if (plugin_instance == NULL)
     plugin_instance = "default";
-  snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
-           plugin_instance, category);
+  ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
+            plugin_instance, category);
 
   sstrncpy(vl.type, type, sizeof(vl.type));
 
@@ -1546,7 +1546,8 @@ static int varnish_init(void) /* {{{ */
       /* callback  = */ varnish_read,
       /* interval  = */ 0,
       &(user_data_t){
-          .data = conf, .free_func = varnish_config_free,
+          .data = conf,
+          .free_func = varnish_config_free,
       });
 
   return 0;
@@ -1751,7 +1752,7 @@ static int varnish_config_instance(const oconfig_item_t *ci) /* {{{ */
       !conf->collect_mgt && !conf->collect_lck && !conf->collect_mempool &&
       !conf->collect_mse
 #endif
-      ) {
+  ) {
     WARNING("Varnish plugin: No metric has been configured for "
             "instance \"%s\". Disabling this instance.",
             (conf->instance == NULL) ? "localhost" : conf->instance);
@@ -1759,8 +1760,8 @@ static int varnish_config_instance(const oconfig_item_t *ci) /* {{{ */
     return EINVAL;
   }
 
-  snprintf(callback_name, sizeof(callback_name), "varnish/%s",
-           (conf->instance == NULL) ? "localhost" : conf->instance);
+  ssnprintf(callback_name, sizeof(callback_name), "varnish/%s",
+            (conf->instance == NULL) ? "localhost" : conf->instance);
 
   plugin_register_complex_read(
       /* group = */ "varnish",
@@ -1768,7 +1769,8 @@ static int varnish_config_instance(const oconfig_item_t *ci) /* {{{ */
       /* callback  = */ varnish_read,
       /* interval  = */ 0,
       &(user_data_t){
-          .data = conf, .free_func = varnish_config_free,
+          .data = conf,
+          .free_func = varnish_config_free,
       });
 
   have_instance = true;
index b9b224e..01c7c77 100644 (file)
@@ -131,16 +131,16 @@ static bool report_network_interfaces = true;
 static virt_notif_thread_t notif_thread;
 
 const char *domain_states[] = {
-        [VIR_DOMAIN_NOSTATE] = "no state",
-        [VIR_DOMAIN_RUNNING] = "the domain is running",
-        [VIR_DOMAIN_BLOCKED] = "the domain is blocked on resource",
-        [VIR_DOMAIN_PAUSED] = "the domain is paused by user",
-        [VIR_DOMAIN_SHUTDOWN] = "the domain is being shut down",
-        [VIR_DOMAIN_SHUTOFF] = "the domain is shut off",
-        [VIR_DOMAIN_CRASHED] = "the domain is crashed",
+    [VIR_DOMAIN_NOSTATE] = "no state",
+    [VIR_DOMAIN_RUNNING] = "the domain is running",
+    [VIR_DOMAIN_BLOCKED] = "the domain is blocked on resource",
+    [VIR_DOMAIN_PAUSED] = "the domain is paused by user",
+    [VIR_DOMAIN_SHUTDOWN] = "the domain is being shut down",
+    [VIR_DOMAIN_SHUTOFF] = "the domain is shut off",
+    [VIR_DOMAIN_CRASHED] = "the domain is crashed",
 #ifdef HAVE_DOM_STATE_PMSUSPENDED
-        [VIR_DOMAIN_PMSUSPENDED] =
-            "the domain is suspended by guest power management",
+    [VIR_DOMAIN_PMSUSPENDED] =
+        "the domain is suspended by guest power management",
 #endif
 };
 
@@ -352,107 +352,99 @@ static int map_domain_event_detail_to_reason(int event, int detail) {
 
 #define DOMAIN_STATE_REASON_MAX_SIZE 20
 const char *domain_reasons[][DOMAIN_STATE_REASON_MAX_SIZE] = {
-        [VIR_DOMAIN_NOSTATE][VIR_DOMAIN_NOSTATE_UNKNOWN] =
-            "the reason is unknown",
-
-        [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_UNKNOWN] =
-            "the reason is unknown",
-        [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_BOOTED] =
-            "normal startup from boot",
-        [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_MIGRATED] =
-            "migrated from another host",
-        [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_RESTORED] =
-            "restored from a state file",
-        [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_FROM_SNAPSHOT] =
-            "restored from snapshot",
-        [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_UNPAUSED] =
-            "returned from paused state",
-        [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_MIGRATION_CANCELED] =
-            "returned from migration",
-        [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_SAVE_CANCELED] =
-            "returned from failed save process",
+    [VIR_DOMAIN_NOSTATE][VIR_DOMAIN_NOSTATE_UNKNOWN] = "the reason is unknown",
+
+    [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_UNKNOWN] = "the reason is unknown",
+    [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_BOOTED] =
+        "normal startup from boot",
+    [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_MIGRATED] =
+        "migrated from another host",
+    [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_RESTORED] =
+        "restored from a state file",
+    [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_FROM_SNAPSHOT] =
+        "restored from snapshot",
+    [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_UNPAUSED] =
+        "returned from paused state",
+    [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_MIGRATION_CANCELED] =
+        "returned from migration",
+    [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_SAVE_CANCELED] =
+        "returned from failed save process",
 #ifdef HAVE_DOM_REASON_RUNNING_WAKEUP
-        [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_WAKEUP] =
-            "returned from pmsuspended due to wakeup event",
+    [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_WAKEUP] =
+        "returned from pmsuspended due to wakeup event",
 #endif
 #ifdef HAVE_DOM_REASON_CRASHED
-        [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_CRASHED] =
-            "resumed from crashed",
+    [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_CRASHED] = "resumed from crashed",
 #endif
 #ifdef HAVE_DOM_REASON_POSTCOPY
-        [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_POSTCOPY] =
-            "running in post-copy migration mode",
-#endif
-        [VIR_DOMAIN_BLOCKED][VIR_DOMAIN_BLOCKED_UNKNOWN] =
-            "the reason is unknown",
-
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_UNKNOWN] =
-            "the reason is unknown",
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_USER] = "paused on user request",
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_MIGRATION] =
-            "paused for offline migration",
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_SAVE] = "paused for save",
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_DUMP] =
-            "paused for offline core dump",
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_IOERROR] =
-            "paused due to a disk I/O error",
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_WATCHDOG] =
-            "paused due to a watchdog event",
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_FROM_SNAPSHOT] =
-            "paused after restoring from snapshot",
+    [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_POSTCOPY] =
+        "running in post-copy migration mode",
+#endif
+    [VIR_DOMAIN_BLOCKED][VIR_DOMAIN_BLOCKED_UNKNOWN] = "the reason is unknown",
+
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_UNKNOWN] = "the reason is unknown",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_USER] = "paused on user request",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_MIGRATION] =
+        "paused for offline migration",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_SAVE] = "paused for save",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_DUMP] =
+        "paused for offline core dump",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_IOERROR] =
+        "paused due to a disk I/O error",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_WATCHDOG] =
+        "paused due to a watchdog event",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_FROM_SNAPSHOT] =
+        "paused after restoring from snapshot",
 #ifdef HAVE_DOM_REASON_PAUSED_SHUTTING_DOWN
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_SHUTTING_DOWN] =
-            "paused during shutdown process",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_SHUTTING_DOWN] =
+        "paused during shutdown process",
 #endif
 #ifdef HAVE_DOM_REASON_PAUSED_SNAPSHOT
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_SNAPSHOT] =
-            "paused while creating a snapshot",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_SNAPSHOT] =
+        "paused while creating a snapshot",
 #endif
 #ifdef HAVE_DOM_REASON_PAUSED_CRASHED
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_CRASHED] =
-            "paused due to a guest crash",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_CRASHED] =
+        "paused due to a guest crash",
 #endif
 #ifdef HAVE_DOM_REASON_PAUSED_STARTING_UP
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_STARTING_UP] =
-            "the domain is being started",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_STARTING_UP] =
+        "the domain is being started",
 #endif
 #ifdef HAVE_DOM_REASON_POSTCOPY
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_POSTCOPY] =
-            "paused for post-copy migration",
-        [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_POSTCOPY_FAILED] =
-            "paused after failed post-copy",
-#endif
-        [VIR_DOMAIN_SHUTDOWN][VIR_DOMAIN_SHUTDOWN_UNKNOWN] =
-            "the reason is unknown",
-        [VIR_DOMAIN_SHUTDOWN][VIR_DOMAIN_SHUTDOWN_USER] =
-            "shutting down on user request",
-
-        [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_UNKNOWN] =
-            "the reason is unknown",
-        [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_SHUTDOWN] = "normal shutdown",
-        [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_DESTROYED] = "forced poweroff",
-        [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_CRASHED] = "domain crashed",
-        [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_MIGRATED] =
-            "migrated to another host",
-        [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_SAVED] = "saved to a file",
-        [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_FAILED] =
-            "domain failed to start",
-        [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT] =
-            "restored from a snapshot which was taken while domain was shutoff",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_POSTCOPY] =
+        "paused for post-copy migration",
+    [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_POSTCOPY_FAILED] =
+        "paused after failed post-copy",
+#endif
+    [VIR_DOMAIN_SHUTDOWN][VIR_DOMAIN_SHUTDOWN_UNKNOWN] =
+        "the reason is unknown",
+    [VIR_DOMAIN_SHUTDOWN][VIR_DOMAIN_SHUTDOWN_USER] =
+        "shutting down on user request",
+
+    [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_UNKNOWN] = "the reason is unknown",
+    [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_SHUTDOWN] = "normal shutdown",
+    [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_DESTROYED] = "forced poweroff",
+    [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_CRASHED] = "domain crashed",
+    [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_MIGRATED] =
+        "migrated to another host",
+    [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_SAVED] = "saved to a file",
+    [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_FAILED] = "domain failed to start",
+    [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT] =
+        "restored from a snapshot which was taken while domain was shutoff",
 #ifdef HAVE_DOM_REASON_SHUTOFF_DAEMON
-        [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_DAEMON] =
-            "daemon decides to kill domain during reconnection processing",
+    [VIR_DOMAIN_SHUTOFF][VIR_DOMAIN_SHUTOFF_DAEMON] =
+        "daemon decides to kill domain during reconnection processing",
 #endif
 
-        [VIR_DOMAIN_CRASHED][VIR_DOMAIN_CRASHED_UNKNOWN] =
-            "the reason is unknown",
+    [VIR_DOMAIN_CRASHED][VIR_DOMAIN_CRASHED_UNKNOWN] = "the reason is unknown",
 #ifdef VIR_DOMAIN_CRASHED_PANICKED
-        [VIR_DOMAIN_CRASHED][VIR_DOMAIN_CRASHED_PANICKED] = "domain panicked",
+    [VIR_DOMAIN_CRASHED][VIR_DOMAIN_CRASHED_PANICKED] = "domain panicked",
 #endif
 
 #ifdef HAVE_DOM_STATE_PMSUSPENDED
-        [VIR_DOMAIN_PMSUSPENDED][VIR_DOMAIN_PMSUSPENDED_UNKNOWN] =
-            "the reason is unknown",
+    [VIR_DOMAIN_PMSUSPENDED][VIR_DOMAIN_PMSUSPENDED_UNKNOWN] =
+        "the reason is unknown",
 #endif
 };
 #endif /* HAVE_DOM_REASON */
@@ -732,7 +724,10 @@ static int get_block_stats(struct lv_block_stats *bstats,
       ERROR(PLUGIN_NAME " plugin: %s failed: %s", (s), err->message);          \
   } while (0)
 
-static char *metadata_get_hostname(virDomainPtr dom) {
+enum metadata_set_type_e { META_APPEND_HOST, META_APPEND_PLUGIN_INSTANCE };
+
+static void set_field_from_metadata(value_list_t *vl, virDomainPtr dom,
+                                    enum metadata_set_type_e field) {
   const char *xpath_str = NULL;
   if (hm_xpath == NULL)
     xpath_str = "/instance/name/text()";
@@ -742,17 +737,18 @@ static char *metadata_get_hostname(virDomainPtr dom) {
   const char *namespace = NULL;
   if (hm_ns == NULL) {
     namespace = "http://openstack.org/xmlns/libvirt/nova/1.0";
-  } else {
+  } // namespace =hm_ns;
+  else {
     namespace = hm_ns;
   }
 
   char *metadata_str = virDomainGetMetadata(
       dom, VIR_DOMAIN_METADATA_ELEMENT, namespace, VIR_DOMAIN_AFFECT_CURRENT);
   if (metadata_str == NULL) {
-    return NULL;
+    return;
   }
 
-  char *hostname = NULL;
+  const char *value = NULL;
   xmlXPathContextPtr xpath_ctx = NULL;
   xmlXPathObjectPtr xpath_obj = NULL;
   xmlNodePtr xml_node = NULL;
@@ -796,18 +792,25 @@ static char *metadata_get_hostname(virDomainPtr dom) {
 
   xml_node = xpath_obj->nodesetval->nodeTab[0];
   if (xml_node->type == XML_TEXT_NODE) {
-    hostname = strdup((const char *)xml_node->content);
+    value = (const char *)xml_node->content;
   } else if (xml_node->type == XML_ATTRIBUTE_NODE) {
-    hostname = strdup((const char *)xml_node->children->content);
+    value = (const char *)xml_node->children->content;
   } else {
     ERROR(PLUGIN_NAME " plugin: xmlXPathEval(%s) unsupported node type %d",
           xpath_str, xml_node->type);
     goto metadata_end;
   }
 
-  if (hostname == NULL) {
-    ERROR(PLUGIN_NAME " plugin: strdup(%s) hostname failed", xpath_str);
+  if (value == NULL)
     goto metadata_end;
+
+  switch (field) {
+  case META_APPEND_HOST:
+    SSTRNCAT(vl->host, value, sizeof(vl->host));
+    break;
+  case META_APPEND_PLUGIN_INSTANCE:
+    SSTRNCAT(vl->plugin_instance, value, sizeof(vl->plugin_instance));
+    break;
   }
 
 metadata_end:
@@ -818,7 +821,6 @@ metadata_end:
   if (xml_doc)
     xmlFreeDoc(xml_doc);
   sfree(metadata_str);
-  return hostname;
 }
 
 static void init_value_list(value_list_t *vl, virDomainPtr dom) {
@@ -853,9 +855,7 @@ static void init_value_list(value_list_t *vl, virDomainPtr dom) {
         SSTRNCAT(vl->host, uuid, sizeof(vl->host));
       break;
     case hf_metadata:
-      name = metadata_get_hostname(dom);
-      if (name)
-        SSTRNCAT(vl->host, name, sizeof(vl->host));
+      set_field_from_metadata(vl, dom, META_APPEND_HOST);
       break;
     }
   }
@@ -881,13 +881,10 @@ static void init_value_list(value_list_t *vl, virDomainPtr dom) {
         SSTRNCAT(vl->plugin_instance, uuid, sizeof(vl->plugin_instance));
       break;
     case plginst_metadata:
-      name = metadata_get_hostname(dom);
-      if (name)
-        SSTRNCAT(vl->plugin_instance, name, sizeof(vl->plugin_instance));
+      set_field_from_metadata(vl, dom, META_APPEND_PLUGIN_INSTANCE);
       break;
     }
   }
-
 } /* void init_value_list */
 
 static int init_notif(notification_t *notif, const virDomainPtr domain,
@@ -957,7 +954,8 @@ static void memory_stats_submit(gauge_t value, virDomainPtr dom,
 static void submit_derive2(const char *type, derive_t v0, derive_t v1,
                            virDomainPtr dom, const char *devname) {
   value_t values[] = {
-      {.derive = v0}, {.derive = v1},
+      {.derive = v0},
+      {.derive = v1},
   };
 
   submit(dom, type, devname, values, STATIC_ARRAY_SIZE(values));
@@ -1009,7 +1007,7 @@ static void vcpu_submit(derive_t value, virDomainPtr dom, int vcpu_nr,
                         const char *type) {
   char type_instance[DATA_MAX_NAME_LEN];
 
-  snprintf(type_instance, sizeof(type_instance), "%d", vcpu_nr);
+  ssnprintf(type_instance, sizeof(type_instance), "%d", vcpu_nr);
   submit(dom, type, type_instance, &(value_t){.derive = value}, 1);
 }
 
@@ -1031,8 +1029,8 @@ static void disk_block_stats_submit(struct lv_block_stats *bstats,
   }
 
   char flush_type_instance[DATA_MAX_NAME_LEN];
-  snprintf(flush_type_instance, sizeof(flush_type_instance), "flush-%s",
-           type_instance);
+  ssnprintf(flush_type_instance, sizeof(flush_type_instance), "flush-%s",
+            type_instance);
 
   if ((bstats->bi.rd_req != -1) && (bstats->bi.wr_req != -1))
     submit_derive2("disk_ops", (derive_t)bstats->bi.rd_req,
@@ -1135,8 +1133,8 @@ static void domain_state_submit_notif(virDomainPtr dom, int state, int reason) {
   const char *reason_str = "N/A";
 #endif
 
-  snprintf(msg, sizeof(msg), "Domain state: %s. Reason: %s", state_str,
-           reason_str);
+  ssnprintf(msg, sizeof(msg), "Domain state: %s. Reason: %s", state_str,
+            reason_str);
 
   int severity;
   switch (state) {
@@ -1592,7 +1590,8 @@ static void vcpu_pin_submit(virDomainPtr dom, int max_cpus, int vcpu,
     char type_instance[DATA_MAX_NAME_LEN];
     bool is_set = VIR_CPU_USABLE(cpu_maps, cpu_map_len, vcpu, cpu);
 
-    snprintf(type_instance, sizeof(type_instance), "vcpu_%d-cpu_%d", vcpu, cpu);
+    ssnprintf(type_instance, sizeof(type_instance), "vcpu_%d-cpu_%d", vcpu,
+              cpu);
     submit(dom, "cpu_affinity", type_instance, &(value_t){.gauge = is_set}, 1);
   }
 }
@@ -1717,7 +1716,8 @@ static int submit_domain_state(virDomainPtr domain) {
   }
 
   value_t values[] = {
-      {.gauge = (gauge_t)domain_state}, {.gauge = (gauge_t)domain_reason},
+      {.gauge = (gauge_t)domain_state},
+      {.gauge = (gauge_t)domain_reason},
   };
 
   submit(domain, "domain_state", NULL, values, STATIC_ARRAY_SIZE(values));
@@ -1801,7 +1801,8 @@ static int get_memory_stats(virDomainPtr domain) {
 
   if (min_flt > 0 || maj_flt > 0) {
     value_t values[] = {
-        {.gauge = (gauge_t)min_flt}, {.gauge = (gauge_t)maj_flt},
+        {.gauge = (gauge_t)min_flt},
+        {.gauge = (gauge_t)maj_flt},
     };
     submit(domain, "ps_pagefaults", NULL, values, STATIC_ARRAY_SIZE(values));
   }
@@ -2520,7 +2521,7 @@ static int lv_init_instance(size_t i, plugin_read_cb callback) {
 
   memset(lv_ud, 0, sizeof(*lv_ud));
 
-  snprintf(inst->tag, sizeof(inst->tag), "%s-%" PRIsz, PLUGIN_NAME, i);
+  ssnprintf(inst->tag, sizeof(inst->tag), "%s-%" PRIsz, PLUGIN_NAME, i);
   inst->id = i;
 
   user_data_t *ud = &(lv_ud->ud);
@@ -2590,8 +2591,8 @@ static int lv_domain_get_tag(xmlXPathContextPtr xpath_ctx, const char *dom_name,
     goto done;
   }
 
-  snprintf(xpath_str, sizeof(xpath_str), "/domain/metadata/%s:%s/text()",
-           METADATA_VM_PARTITION_PREFIX, METADATA_VM_PARTITION_ELEMENT);
+  ssnprintf(xpath_str, sizeof(xpath_str), "/domain/metadata/%s:%s/text()",
+            METADATA_VM_PARTITION_PREFIX, METADATA_VM_PARTITION_ELEMENT);
   xpath_obj = xmlXPathEvalExpression((xmlChar *)xpath_str, xpath_ctx);
   if (xpath_obj == NULL) {
     ERROR(PLUGIN_NAME " plugin: xmlXPathEval(%s) failed on domain %s",
@@ -2793,7 +2794,7 @@ static void lv_add_network_interfaces(struct lv_read_state *state,
       break;
     case if_number: {
       char number_string[4];
-      snprintf(number_string, sizeof(number_string), "%d", itf_number);
+      ssnprintf(number_string, sizeof(number_string), "%d", itf_number);
       if (ignore_device_match(il_interface_devices, domname, number_string) !=
           0)
         device_ignored = true;
@@ -3094,7 +3095,7 @@ static int add_interface_device(struct lv_read_state *state, virDomainPtr dom,
   }
 
   char number_string[21];
-  snprintf(number_string, sizeof(number_string), "interface-%u", number);
+  ssnprintf(number_string, sizeof(number_string), "interface-%u", number);
   char *number_copy = strdup(number_string);
   if (!number_copy) {
     sfree(path_copy);
@@ -3133,7 +3134,7 @@ static int ignore_device_match(ignorelist_t *il, const char *domname,
     ERROR(PLUGIN_NAME " plugin: malloc failed.");
     return 0;
   }
-  snprintf(name, n, "%s:%s", domname, devpath);
+  ssnprintf(name, n, "%s:%s", domname, devpath);
   int r = ignorelist_match(il, name);
   sfree(name);
   return r;
index 2ab7dda..a4112bb 100644 (file)
@@ -60,7 +60,8 @@ static void submit(const char *plugin_instance, const char *type,
 static void submit_two(const char *plugin_instance, const char *type,
                        const char *type_instance, derive_t c0, derive_t c1) {
   value_t values[] = {
-      {.derive = c0}, {.derive = c1},
+      {.derive = c0},
+      {.derive = c1},
   };
 
   submit(plugin_instance, type, type_instance, values,
index e1d1b35..424a218 100644 (file)
@@ -57,7 +57,8 @@ static void traffic_submit(const char *plugin_instance,
                            derive_t tx) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.derive = rx}, {.derive = tx},
+      {.derive = rx},
+      {.derive = tx},
   };
 
   vl.values = values;
@@ -74,7 +75,9 @@ static void load_submit(const char *plugin_instance, gauge_t snum, gauge_t mnum,
                         gauge_t lnum) {
   value_list_t vl = VALUE_LIST_INIT;
   value_t values[] = {
-      {.gauge = snum}, {.gauge = mnum}, {.gauge = lnum},
+      {.gauge = snum},
+      {.gauge = mnum},
+      {.gauge = lnum},
   };
 
   vl.values = values;
index cb6793d..dc3b2c7 100644 (file)
@@ -552,7 +552,8 @@ static int wg_config_node(oconfig_item_t *ci) {
 
   plugin_register_write(callback_name, wg_write,
                         &(user_data_t){
-                            .data = cb, .free_func = wg_callback_free,
+                            .data = cb,
+                            .free_func = wg_callback_free,
                         });
 
   plugin_register_flush(callback_name, wg_flush, &(user_data_t){.data = cb});
index 74fdaca..7cd19c3 100644 (file)
@@ -815,7 +815,8 @@ static int wh_config_node(oconfig_item_t *ci) /* {{{ */
         callback_name, cb->location);
 
   user_data_t user_data = {
-      .data = cb, .free_func = wh_callback_free,
+      .data = cb,
+      .free_func = wh_callback_free,
   };
 
   if (cb->send_metrics) {
index 4c7a471..09bb639 100644 (file)
@@ -97,7 +97,7 @@ static uint32_t kafka_hash(const char *keydata, size_t keylen) {
 #define KAFKA_RANDOM_KEY_BUFFER                                                \
   (char[KAFKA_RANDOM_KEY_SIZE]) { "" }
 static char *kafka_random_key(char buffer[static KAFKA_RANDOM_KEY_SIZE]) {
-  snprintf(buffer, KAFKA_RANDOM_KEY_SIZE, "%08" PRIX32, cdrand_u());
+  ssnprintf(buffer, KAFKA_RANDOM_KEY_SIZE, "%08" PRIX32, cdrand_u());
   return buffer;
 }
 
@@ -410,14 +410,14 @@ static void kafka_config_topic(rd_kafka_conf_t *conf,
   rd_kafka_topic_conf_set_partitioner_cb(tctx->conf, kafka_partition);
   rd_kafka_topic_conf_set_opaque(tctx->conf, tctx);
 
-  snprintf(callback_name, sizeof(callback_name), "write_kafka/%s",
-           tctx->topic_name);
+  ssnprintf(callback_name, sizeof(callback_name), "write_kafka/%s",
+            tctx->topic_name);
 
-  status = plugin_register_write(
-      callback_name, kafka_write,
-      &(user_data_t){
-          .data = tctx, .free_func = kafka_topic_context_free,
-      });
+  status = plugin_register_write(callback_name, kafka_write,
+                                 &(user_data_t){
+                                     .data = tctx,
+                                     .free_func = kafka_topic_context_free,
+                                 });
   if (status != 0) {
     WARNING("write_kafka plugin: plugin_register_write (\"%s\") "
             "failed with status %i.",
index 0cb1e02..b43906e 100644 (file)
@@ -370,11 +370,11 @@ static int wm_config_node(oconfig_item_t *ci) /* {{{ */
 
     snprintf(cb_name, sizeof(cb_name), "write_mongodb/%s", node->name);
 
-    status =
-        plugin_register_write(cb_name, wm_write,
-                              &(user_data_t){
-                                  .data = node, .free_func = wm_config_free,
-                              });
+    status = plugin_register_write(cb_name, wm_write,
+                                   &(user_data_t){
+                                       .data = node,
+                                       .free_func = wm_config_free,
+                                   });
     INFO("write_mongodb plugin: registered write plugin %s %d", cb_name,
          status);
   }
index 96e71ca..b904022 100644 (file)
@@ -156,7 +156,8 @@ static char *format_labels(char *buffer, size_t buffer_size,
 #define LABEL_BUFFER_SIZE (LABEL_KEY_SIZE + LABEL_VALUE_SIZE + 4)
 
   char *labels[3] = {
-      (char[LABEL_BUFFER_SIZE]){0}, (char[LABEL_BUFFER_SIZE]){0},
+      (char[LABEL_BUFFER_SIZE]){0},
+      (char[LABEL_BUFFER_SIZE]){0},
       (char[LABEL_BUFFER_SIZE]){0},
   };
 
@@ -164,8 +165,8 @@ static char *format_labels(char *buffer, size_t buffer_size,
    * know that they are sane. */
   for (size_t i = 0; i < m->n_label; i++) {
     char value[LABEL_VALUE_SIZE];
-    snprintf(labels[i], LABEL_BUFFER_SIZE, "%s=\"%s\"", m->label[i]->name,
-             escape_label_value(value, sizeof(value), m->label[i]->value));
+    ssnprintf(labels[i], LABEL_BUFFER_SIZE, "%s=\"%s\"", m->label[i]->name,
+              escape_label_value(value, sizeof(value), m->label[i]->value));
   }
 
   strjoin(buffer, buffer_size, labels, m->n_label, ",");
@@ -183,13 +184,13 @@ static void format_text(ProtobufCBuffer *buffer) {
   while (c_avl_iterator_next(iter, (void *)&unused_name, (void *)&fam) == 0) {
     char line[1024]; /* 4x DATA_MAX_NAME_LEN? */
 
-    snprintf(line, sizeof(line), "# HELP %s %s\n", fam->name, fam->help);
+    ssnprintf(line, sizeof(line), "# HELP %s %s\n", fam->name, fam->help);
     buffer->append(buffer, strlen(line), (uint8_t *)line);
 
-    snprintf(line, sizeof(line), "# TYPE %s %s\n", fam->name,
-             (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__GAUGE)
-                 ? "gauge"
-                 : "counter");
+    ssnprintf(line, sizeof(line), "# TYPE %s %s\n", fam->name,
+              (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__GAUGE)
+                  ? "gauge"
+                  : "counter");
     buffer->append(buffer, strlen(line), (uint8_t *)line);
 
     for (size_t i = 0; i < fam->n_metric; i++) {
@@ -199,17 +200,17 @@ static void format_text(ProtobufCBuffer *buffer) {
 
       char timestamp_ms[24] = "";
       if (m->has_timestamp_ms)
-        snprintf(timestamp_ms, sizeof(timestamp_ms), " %" PRIi64,
-                 m->timestamp_ms);
+        ssnprintf(timestamp_ms, sizeof(timestamp_ms), " %" PRIi64,
+                  m->timestamp_ms);
 
       if (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__GAUGE)
-        snprintf(line, sizeof(line), "%s{%s} " GAUGE_FORMAT "%s\n", fam->name,
-                 format_labels(labels, sizeof(labels), m), m->gauge->value,
-                 timestamp_ms);
+        ssnprintf(line, sizeof(line), "%s{%s} " GAUGE_FORMAT "%s\n", fam->name,
+                  format_labels(labels, sizeof(labels), m), m->gauge->value,
+                  timestamp_ms);
       else /* if (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__COUNTER) */
-        snprintf(line, sizeof(line), "%s{%s} %.0f%s\n", fam->name,
-                 format_labels(labels, sizeof(labels), m), m->counter->value,
-                 timestamp_ms);
+        ssnprintf(line, sizeof(line), "%s{%s} %.0f%s\n", fam->name,
+                  format_labels(labels, sizeof(labels), m), m->counter->value,
+                  timestamp_ms);
 
       buffer->append(buffer, strlen(line), (uint8_t *)line);
     }
@@ -217,8 +218,8 @@ static void format_text(ProtobufCBuffer *buffer) {
   c_avl_iterator_destroy(iter);
 
   char server[1024];
-  snprintf(server, sizeof(server), "\n# collectd/write_prometheus %s at %s\n",
-           PACKAGE_VERSION, hostname_g);
+  ssnprintf(server, sizeof(server), "\n# collectd/write_prometheus %s at %s\n",
+            PACKAGE_VERSION, hostname_g);
   buffer->append(buffer, strlen(server), (uint8_t *)server);
 
   pthread_mutex_unlock(&metrics_lock);
@@ -635,7 +636,7 @@ metric_family_create(char *name, data_set_t const *ds, value_list_t const *vl,
   msg->name = name;
 
   char help[1024];
-  snprintf(
+  ssnprintf(
       help, sizeof(help),
       "write_prometheus plugin: '%s' Type: '%s', Dstype: '%s', Dsname: '%s'",
       vl->plugin, vl->type, DS_TYPE_TO_STRING(ds->ds[ds_index].type),
@@ -744,7 +745,7 @@ static void prom_logger(__attribute__((unused)) void *arg, char const *fmt,
 static int prom_open_socket(int addrfamily) {
   /* {{{ */
   char service[NI_MAXSERV];
-  snprintf(service, sizeof(service), "%hu", httpd_port);
+  ssnprintf(service, sizeof(service), "%hu", httpd_port);
 
   struct addrinfo *res;
   int status = getaddrinfo(httpd_host, service,
index 324999c..32005cd 100644 (file)
@@ -71,9 +71,10 @@ static int wr_write(const data_set_t *ds, /* {{{ */
   status = FORMAT_VL(ident, sizeof(ident), vl);
   if (status != 0)
     return status;
-  snprintf(key, sizeof(key), "%s%s",
-           (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX, ident);
-  snprintf(time, sizeof(time), "%.9f", CDTIME_T_TO_DOUBLE(vl->time));
+  ssnprintf(key, sizeof(key), "%s%s",
+            (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX,
+            ident);
+  ssnprintf(time, sizeof(time), "%.9f", CDTIME_T_TO_DOUBLE(vl->time));
 
   value_size = sizeof(value);
   value_ptr = &value[0];
@@ -239,13 +240,13 @@ static int wr_config_node(oconfig_item_t *ci) /* {{{ */
   if (status == 0) {
     char cb_name[sizeof("write_redis/") + DATA_MAX_NAME_LEN];
 
-    snprintf(cb_name, sizeof(cb_name), "write_redis/%s", node->name);
+    ssnprintf(cb_name, sizeof(cb_name), "write_redis/%s", node->name);
 
-    status =
-        plugin_register_write(cb_name, wr_write,
-                              &(user_data_t){
-                                  .data = node, .free_func = wr_config_free,
-                              });
+    status = plugin_register_write(cb_name, wr_write,
+                                   &(user_data_t){
+                                       .data = node,
+                                       .free_func = wr_config_free,
+                                   });
   }
 
   if (status != 0)
index 8056993..201ac51 100644 (file)
@@ -291,17 +291,18 @@ wrr_value_to_event(struct riemann_host const *host, /* {{{ */
               vl->type_instance);
   if (host->always_append_ds || (ds->ds_num > 1)) {
     if (host->event_service_prefix == NULL)
-      snprintf(service_buffer, sizeof(service_buffer), "%s/%s", &name_buffer[1],
-               ds->ds[index].name);
+      ssnprintf(service_buffer, sizeof(service_buffer), "%s/%s",
+                &name_buffer[1], ds->ds[index].name);
     else
-      snprintf(service_buffer, sizeof(service_buffer), "%s%s/%s",
-               host->event_service_prefix, &name_buffer[1], ds->ds[index].name);
+      ssnprintf(service_buffer, sizeof(service_buffer), "%s%s/%s",
+                host->event_service_prefix, &name_buffer[1],
+                ds->ds[index].name);
   } else {
     if (host->event_service_prefix == NULL)
       sstrncpy(service_buffer, &name_buffer[1], sizeof(service_buffer));
     else
-      snprintf(service_buffer, sizeof(service_buffer), "%s%s",
-               host->event_service_prefix, &name_buffer[1]);
+      ssnprintf(service_buffer, sizeof(service_buffer), "%s%s",
+                host->event_service_prefix, &name_buffer[1]);
   }
 
   riemann_event_set(
@@ -349,8 +350,8 @@ wrr_value_to_event(struct riemann_host const *host, /* {{{ */
   if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL)) {
     char ds_type[DATA_MAX_NAME_LEN];
 
-    snprintf(ds_type, sizeof(ds_type), "%s:rate",
-             DS_TYPE_TO_STRING(ds->ds[index].type));
+    ssnprintf(ds_type, sizeof(ds_type), "%s:rate",
+              DS_TYPE_TO_STRING(ds->ds[index].type));
     riemann_event_string_attribute_add(event, "ds_type", ds_type);
   } else {
     riemann_event_string_attribute_add(event, "ds_type",
@@ -360,7 +361,7 @@ wrr_value_to_event(struct riemann_host const *host, /* {{{ */
   {
     char ds_index[DATA_MAX_NAME_LEN];
 
-    snprintf(ds_index, sizeof(ds_index), "%" PRIsz, index);
+    ssnprintf(ds_index, sizeof(ds_index), "%" PRIsz, index);
     riemann_event_string_attribute_add(event, "ds_index", ds_index);
   }
 
@@ -794,8 +795,8 @@ static int wrr_config_node(oconfig_item_t *ci) /* {{{ */
     return status;
   }
 
-  snprintf(callback_name, sizeof(callback_name), "write_riemann/%s",
-           host->name);
+  ssnprintf(callback_name, sizeof(callback_name), "write_riemann/%s",
+            host->name);
 
   user_data_t ud = {.data = host, .free_func = wrr_free};
 
index fd0192a..dfa1d7c 100644 (file)
@@ -109,8 +109,8 @@ static char *wg_get_authorization_header(wg_callback_t *cb) { /* {{{ */
     return NULL;
   }
 
-  status = snprintf(authorization_header, sizeof(authorization_header),
-                    "Authorization: Bearer %s", access_token);
+  status = ssnprintf(authorization_header, sizeof(authorization_header),
+                     "Authorization: Bearer %s", access_token);
   if ((status < 1) || ((size_t)status >= sizeof(authorization_header)))
     return NULL;
 
@@ -160,9 +160,9 @@ static char *api_error_string(api_error_t *err, char *buffer,
   if (err == NULL) {
     strncpy(buffer, "Unknown error (API error is NULL)", buffer_size);
   } else if (err->message == NULL) {
-    snprintf(buffer, buffer_size, "API error %d", err->code);
+    ssnprintf(buffer, buffer_size, "API error %d", err->code);
   } else {
-    snprintf(buffer, buffer_size, "API error %d: %s", err->code, err->message);
+    ssnprintf(buffer, buffer_size, "API error %d: %s", err->code, err->message);
   }
 
   return buffer;
@@ -251,8 +251,8 @@ static int do_post(wg_callback_t *cb, char const *url, void const *payload,
 static int wg_call_metricdescriptor_create(wg_callback_t *cb,
                                            char const *payload) {
   char url[1024];
-  snprintf(url, sizeof(url), "%s/projects/%s/metricDescriptors", cb->url,
-           cb->project);
+  ssnprintf(url, sizeof(url), "%s/projects/%s/metricDescriptors", cb->url,
+            cb->project);
   wg_memory_t response = {0};
 
   int status = do_post(cb, url, payload, &response);
@@ -273,7 +273,8 @@ static int wg_call_metricdescriptor_create(wg_callback_t *cb,
 
 static int wg_call_timeseries_write(wg_callback_t *cb, char const *payload) {
   char url[1024];
-  snprintf(url, sizeof(url), "%s/projects/%s/timeSeries", cb->url, cb->project);
+  ssnprintf(url, sizeof(url), "%s/projects/%s/timeSeries", cb->url,
+            cb->project);
   wg_memory_t response = {0};
 
   int status = do_post(cb, url, payload, &response);
index d18a93f..3364697 100644 (file)
@@ -127,7 +127,7 @@ static long long get_zfs_value(kstat_t *dummy __attribute__((unused)),
   size_t valuelen = sizeof(value);
   int rv;
 
-  snprintf(buffer, sizeof(buffer), "%s%s", zfs_arcstat, name);
+  ssnprintf(buffer, sizeof(buffer), "%s%s", zfs_arcstat, name);
   rv = sysctlbyname(buffer, (void *)&value, &valuelen,
                     /* new value = */ NULL, /* new length = */ (size_t)0);
   if (rv == 0)
@@ -231,23 +231,6 @@ static int za_read(void) {
     return -1;
   }
 
-  // Ignore the first two lines because they contain information about
-  // the rest of the file.
-  // See kstat_seq_show_headers module/spl/spl-kstat.c of the spl kernel
-  // module.
-  if (fgets(buffer, sizeof(buffer), fh) == NULL) {
-    ERROR("zfs_arc plugin: \"%s\" does not contain a single line.",
-          ZOL_ARCSTATS_FILE);
-    fclose(fh);
-    return (-1);
-  }
-  if (fgets(buffer, sizeof(buffer), fh) == NULL) {
-    ERROR("zfs_arc plugin: \"%s\" does not contain at least two lines.",
-          ZOL_ARCSTATS_FILE);
-    fclose(fh);
-    return (-1);
-  }
-
   while (fgets(buffer, sizeof(buffer), fh) != NULL) {
     char *fields[3];
     value_t v;
@@ -285,10 +268,17 @@ static int za_read(void) {
   za_read_gauge(ksp, "mfu_size", "cache_size", "mfu_size");
   za_read_gauge(ksp, "mru_ghost_size", "cache_size", "mru_ghost_size");
   za_read_gauge(ksp, "mru_size", "cache_size", "mru_size");
-  za_read_gauge(ksp, "other_size", "cache_size", "other_size");
   za_read_gauge(ksp, "p", "cache_size", "p");
   za_read_gauge(ksp, "size", "cache_size", "arc");
 
+  /* The "other_size" value was replaced by more specific values in ZFS on Linux
+   * version 0.7.0 (commit 25458cb)
+   */
+  if (za_read_gauge(ksp, "dbuf_size", "cache_size", "dbuf_size") != 0 ||
+      za_read_gauge(ksp, "dnode_size", "cache_size", "dnode_size") != 0 ||
+      za_read_gauge(ksp, "bonus_size", "cache_size", "bonus_size") != 0)
+    za_read_gauge(ksp, "other_size", "cache_size", "other_size");
+
   /* The "l2_size" value has disappeared from Solaris some time in
    * early 2013, and has only reappeared recently in Solaris 11.2.
    * Stop trying if we ever fail to read it, so we don't spam the log.
index 048b5a2..76bd065 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-DEFAULT_VERSION="5.8.1.git"
+DEFAULT_VERSION="5.9.2.git"
 
 if [ -d .git ]; then
        VERSION="`git describe --dirty=+ --abbrev=7 2> /dev/null | grep collectd | sed -e 's/^collectd-//' -e 's/-/./g'`"